agora inbox for [email protected]  
help / color / mirror / Atom feed
[PATCH v1 2/4] autovac: resolve relopts before vacuuming
791+ messages / 2 participants
[nested] [flat]

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH v1 2/4] autovac: resolve relopts before vacuuming
@ 2025-06-23 19:42 Nathan Bossart <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Nathan Bossart @ 2025-06-23 19:42 UTC (permalink / raw)

---
 src/backend/commands/vacuum.c       |  7 ++--
 src/backend/postmaster/autovacuum.c | 52 +++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 33a33bf6b1c..0015b9ef4b0 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -421,7 +421,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	/*
 	 * Later, in vacuum_rel(), we check if a reloption override was specified.
 	 */
-	params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+	params.max_eager_freeze_failure_rate = -1.0;
 
 	/*
 	 * Create special memory context for cross-transaction storage.
@@ -2195,10 +2195,13 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params,
 	 * Check if the vacuum_max_eager_freeze_failure_rate table storage
 	 * parameter was specified. This overrides the GUC value.
 	 */
-	if (rel->rd_options != NULL &&
+	if (params->max_eager_freeze_failure_rate < 0 &&
+		rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
 		params->max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
+	else
+		params->max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index f86c9fed853..3bedca971ff 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2758,6 +2758,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		int			multixact_freeze_table_age;
 		int			log_min_duration;
 		AutoVacOpts *avopts = (relopts ? &relopts->autovacuum : NULL);
+		VacOptValue index_cleanup;
+		VacOptValue truncate;
+		double		max_eager_freeze_failure_rate;
 
 		/*
 		 * Calculate the vacuum cost parameters and the freeze ages.  If there
@@ -2790,6 +2793,39 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			? avopts->multixact_freeze_table_age
 			: default_multixact_freeze_table_age;
 
+		if (relopts)
+		{
+			switch (relopts->vacuum_index_cleanup)
+			{
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO:
+					index_cleanup = VACOPTVALUE_AUTO;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON:
+					index_cleanup = VACOPTVALUE_ENABLED;
+					break;
+				case STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF:
+					index_cleanup = VACOPTVALUE_DISABLED;
+					break;
+			}
+		}
+		else
+			index_cleanup = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_truncate_set)
+		{
+			if (relopts->vacuum_truncate)
+				truncate = VACOPTVALUE_ENABLED;
+			else
+				truncate = VACOPTVALUE_DISABLED;
+		}
+		else
+			truncate = VACOPTVALUE_UNSPECIFIED;
+
+		if (relopts && relopts->vacuum_max_eager_freeze_failure_rate >= 0)
+			max_eager_freeze_failure_rate = relopts->vacuum_max_eager_freeze_failure_rate;
+		else
+			max_eager_freeze_failure_rate = -1.0;
+
 		tab = palloc(sizeof(autovac_table));
 		tab->at_relid = relid;
 		tab->at_sharedrel = classForm->relisshared;
@@ -2806,13 +2842,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
 
-		/*
-		 * index_cleanup and truncate are unspecified at first in autovacuum.
-		 * They will be filled in with usable values using their reloptions
-		 * (or reloption defaults) later.
-		 */
-		tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
-		tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
+		tab->at_params.index_cleanup = index_cleanup;
+		tab->at_params.truncate = truncate;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
 		tab->at_params.freeze_min_age = freeze_min_age;
@@ -2822,12 +2853,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.is_wraparound = wraparound;
 		tab->at_params.log_min_duration = log_min_duration;
 		tab->at_params.toast_parent = InvalidOid;
-
-		/*
-		 * Later, in vacuum_rel(), we check reloptions for any
-		 * vacuum_max_eager_freeze_failure_rate override.
-		 */
-		tab->at_params.max_eager_freeze_failure_rate = vacuum_max_eager_freeze_failure_rate;
+		tab->at_params.max_eager_freeze_failure_rate = max_eager_freeze_failure_rate;
 		tab->at_storage_param_vac_cost_limit = avopts ?
 			avopts->vacuum_cost_limit : 0;
 		tab->at_storage_param_vac_cost_delay = avopts ?
-- 
2.39.5 (Apple Git-154)


--QWBYbd5Ar5k8NvSv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment;
	filename=v1-0003-autovac-combine-reloptions-correctly.patch



^ permalink  raw  reply  [nested|flat] 791+ messages in thread

* [PATCH 2/2] Provide the executor with information on updated columns.
@ 2026-07-01 13:18 Antonin Houska <[email protected]>
  0 siblings, 0 replies; 791+ messages in thread

From: Antonin Houska @ 2026-07-01 13:18 UTC (permalink / raw)

When replaying data changes, REPACK calls ExecInsertIndexTuples() for each
INSERT and UPDATE. In the latter case, the function needs to determine the
value of the 'indexUnchanged' hint for the index AM. (The hint is always false
for INSERT.) Therefore, REPACK is supposed to specify which columns are
changed by the UPDATE.

So far, REPACK missed to specify the set of updated columns, so the
'indexUnchanged' hint could incorrectly evaluate to true. Although it should
not affect correctness, it can make the index AM use optimizations that are
not appropriate.  Ideally, we should compute the set of updated columns for
each individual UPDATE, however the comparison of the old and new tuple might
add too much overhead.

This patch initializes the set as if all columns were updated. Thus
'indexUnchanged' always evaluates to false. This way the index AM never uses
the related optimizations. It might result in worse structure of the index,
however it seems better to not use the optimizations than to misuse them.
---
 src/backend/commands/repack.c | 40 ++++++++++++++++++++++++++++++++++-
 1 file changed, 39 insertions(+), 1 deletion(-)

diff --git a/src/backend/commands/repack.c b/src/backend/commands/repack.c
index c9b0c047477..f37bb9a21af 100644
--- a/src/backend/commands/repack.c
+++ b/src/backend/commands/repack.c
@@ -62,6 +62,7 @@
 #include "libpq/pqmq.h"
 #include "miscadmin.h"
 #include "optimizer/optimizer.h"
+#include "parser/parse_relation.h"
 #include "pgstat.h"
 #include "replication/logicalrelation.h"
 #include "storage/bufmgr.h"
@@ -3005,13 +3006,50 @@ static void
 initialize_change_context(ChangeContext *chgcxt,
 						  Relation relation, Oid ident_index_id)
 {
+	Bitmapset	*updatedCols = NULL;
+	RangeTblEntry *rte;
+	List	   *perminfos = NIL;
+	RTEPermissionInfo *perminfo;
+
 	chgcxt->cc_rel = relation;
 
 	/* Only initialize fields needed by ExecInsertIndexTuples(). */
 	chgcxt->cc_estate = CreateExecutorState();
 
+	/*
+	 * Initialize updatedCols.
+	 *
+	 * The point is that ExecInsertIndexTuples() should not pass the
+	 * indexUnchanged hint to the index AM unless there's a reason to do
+	 * so. For simplicity, we consider all columns updated.
+	 *
+	 * XXX Should we spend more effort to compare the old and new tuple when
+	 * replaying UPDATE, or at least exclude unchanged TOAST values, like we
+	 * do in logicalrep_write_tuple()?
+	 */
+	for (int i = 0; i < RelationGetDescr(relation)->natts; i++)
+		updatedCols = bms_add_member(updatedCols,
+									 i + 1 - FirstLowInvalidHeapAttributeNumber);
+
+	/*
+	 * In this case, RTE only needs to have ->perminfoindex initialized, but
+	 * there's no reason to not set the fields whose values we have at hand.
+	 */
+	rte = makeNode(RangeTblEntry);
+	rte->rtekind = RTE_RELATION;
+	rte->relid = RelationGetRelid(relation);
+	rte->relkind = RelationGetForm(relation)->relkind;
+	/* Create the RTEPermissionInfo instance (and set ->perminfoindex). */
+	addRTEPermissionInfo(&perminfos, rte);
+	/* Make updatedCols available to the executor functions. */
+	perminfo = getRTEPermissionInfo(perminfos, rte);
+	perminfo->updatedCols = updatedCols;
+
+	ExecInitRangeTable(chgcxt->cc_estate, list_make1(rte), perminfos,
+					   bms_make_singleton(1));
+
 	chgcxt->cc_rri = makeNode(ResultRelInfo);
-	InitResultRelInfo(chgcxt->cc_rri, relation, 0, NULL, 0);
+	InitResultRelInfo(chgcxt->cc_rri, relation, 1, NULL, 0);
 	ExecOpenIndices(chgcxt->cc_rri, false);
 
 	/*
-- 
2.52.0


--=-=-=--





^ permalink  raw  reply  [nested|flat] 791+ messages in thread


end of thread, other threads:[~2026-07-01 13:18 UTC | newest]

Thread overview: 791+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2025-06-23 19:42 [PATCH v1 2/4] autovac: resolve relopts before vacuuming Nathan Bossart <[email protected]>
2026-07-01 13:18 [PATCH 2/2] Provide the executor with information on updated columns. Antonin Houska <[email protected]>

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox