From 2809db6e63eb4c8380203b12fbb31ec6753c540e Mon Sep 17 00:00:00 2001
From: Nathan Bossart <nathan@postgresql.org>
Date: Tue, 24 Mar 2026 16:46:46 -0500
Subject: [PATCH v1 1/1] avoid including vacuum.h in tableam.h and heapam.h

---
 contrib/dblink/dblink.c                    |   1 +
 contrib/tablefunc/tablefunc.c              |   1 +
 src/backend/access/heap/vacuumlazy.c       |  46 ++++-----
 src/backend/catalog/toasting.c             |   1 +
 src/backend/commands/analyze.c             |  26 ++---
 src/backend/commands/cluster.c             |   4 +-
 src/backend/commands/event_trigger.c       |   1 +
 src/backend/commands/vacuum.c              | 111 +++++++++++----------
 src/backend/postmaster/autovacuum.c        |   2 +-
 src/backend/replication/logical/conflict.c |   1 +
 src/backend/replication/logical/worker.c   |   1 +
 src/backend/utils/adt/ri_triggers.c        |   1 +
 src/include/access/heapam.h                |  12 +--
 src/include/access/tableam.h               |   7 +-
 src/include/commands/vacuum.h              |   6 +-
 src/pl/tcl/pltcl.c                         |   1 +
 16 files changed, 117 insertions(+), 105 deletions(-)

diff --git a/contrib/dblink/dblink.c b/contrib/dblink/dblink.c
index ac6127ec1b5..67fc8e39faf 100644
--- a/contrib/dblink/dblink.c
+++ b/contrib/dblink/dblink.c
@@ -59,6 +59,7 @@
 #include "utils/builtins.h"
 #include "utils/fmgroids.h"
 #include "utils/guc.h"
+#include "utils/hsearch.h"
 #include "utils/lsyscache.h"
 #include "utils/memutils.h"
 #include "utils/rel.h"
diff --git a/contrib/tablefunc/tablefunc.c b/contrib/tablefunc/tablefunc.c
index c01a01c5fe7..31f70b7bc10 100644
--- a/contrib/tablefunc/tablefunc.c
+++ b/contrib/tablefunc/tablefunc.c
@@ -43,6 +43,7 @@
 #include "lib/stringinfo.h"
 #include "miscadmin.h"
 #include "utils/builtins.h"
+#include "utils/hsearch.h"
 #include "utils/tuplestore.h"
 
 PG_MODULE_MAGIC_EXT(
diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c
index 696919e35dd..c0205ec6836 100644
--- a/src/backend/access/heap/vacuumlazy.c
+++ b/src/backend/access/heap/vacuumlazy.c
@@ -424,7 +424,7 @@ typedef struct LVSavedErrInfo
 /* non-export function prototypes */
 static void lazy_scan_heap(LVRelState *vacrel);
 static void heap_vacuum_eager_scan_setup(LVRelState *vacrel,
-										 const VacuumParams params);
+										 const VacuumParams *params);
 static BlockNumber heap_vac_scan_next_block(ReadStream *stream,
 											void *callback_private_data,
 											void *per_buffer_data);
@@ -500,7 +500,7 @@ static void restore_vacuum_error_info(LVRelState *vacrel,
  * vacuum options or for relfrozenxid/relminmxid advancement.
  */
 static void
-heap_vacuum_eager_scan_setup(LVRelState *vacrel, const VacuumParams params)
+heap_vacuum_eager_scan_setup(LVRelState *vacrel, const VacuumParams *params)
 {
 	uint32		randseed;
 	BlockNumber allvisible;
@@ -519,7 +519,7 @@ heap_vacuum_eager_scan_setup(LVRelState *vacrel, const VacuumParams params)
 	vacrel->eager_scan_remaining_successes = 0;
 
 	/* If eager scanning is explicitly disabled, just return. */
-	if (params.max_eager_freeze_failure_rate == 0)
+	if (params->max_eager_freeze_failure_rate == 0)
 		return;
 
 	/*
@@ -596,11 +596,11 @@ heap_vacuum_eager_scan_setup(LVRelState *vacrel, const VacuumParams params)
 
 	vacrel->next_eager_scan_region_start = randseed % EAGER_SCAN_REGION_SIZE;
 
-	Assert(params.max_eager_freeze_failure_rate > 0 &&
-		   params.max_eager_freeze_failure_rate <= 1);
+	Assert(params->max_eager_freeze_failure_rate > 0 &&
+		   params->max_eager_freeze_failure_rate <= 1);
 
 	vacrel->eager_scan_max_fails_per_region =
-		params.max_eager_freeze_failure_rate *
+		params->max_eager_freeze_failure_rate *
 		EAGER_SCAN_REGION_SIZE;
 
 	/*
@@ -627,7 +627,7 @@ heap_vacuum_eager_scan_setup(LVRelState *vacrel, const VacuumParams params)
  *		and locked the relation.
  */
 void
-heap_vacuum_rel(Relation rel, const VacuumParams params,
+heap_vacuum_rel(Relation rel, const VacuumParams *params,
 				BufferAccessStrategy bstrategy)
 {
 	LVRelState *vacrel;
@@ -650,9 +650,9 @@ heap_vacuum_rel(Relation rel, const VacuumParams params,
 	char	  **indnames = NULL;
 	Size		dead_items_max_bytes = 0;
 
-	verbose = (params.options & VACOPT_VERBOSE) != 0;
+	verbose = (params->options & VACOPT_VERBOSE) != 0;
 	instrument = (verbose || (AmAutoVacuumWorkerProcess() &&
-							  params.log_vacuum_min_duration >= 0));
+							  params->log_vacuum_min_duration >= 0));
 	if (instrument)
 	{
 		pg_rusage_init(&ru0);
@@ -670,7 +670,7 @@ heap_vacuum_rel(Relation rel, const VacuumParams params,
 								  RelationGetRelid(rel));
 	if (AmAutoVacuumWorkerProcess())
 		pgstat_progress_update_param(PROGRESS_VACUUM_STARTED_BY,
-									 params.is_wraparound
+									 params->is_wraparound
 									 ? PROGRESS_VACUUM_STARTED_BY_AUTOVACUUM_WRAPAROUND
 									 : PROGRESS_VACUUM_STARTED_BY_AUTOVACUUM);
 	else
@@ -723,9 +723,9 @@ heap_vacuum_rel(Relation rel, const VacuumParams params,
 	 * The truncate param allows user to avoid attempting relation truncation,
 	 * though it can't force truncation to happen.
 	 */
-	Assert(params.index_cleanup != VACOPTVALUE_UNSPECIFIED);
-	Assert(params.truncate != VACOPTVALUE_UNSPECIFIED &&
-		   params.truncate != VACOPTVALUE_AUTO);
+	Assert(params->index_cleanup != VACOPTVALUE_UNSPECIFIED);
+	Assert(params->truncate != VACOPTVALUE_UNSPECIFIED &&
+		   params->truncate != VACOPTVALUE_AUTO);
 
 	/*
 	 * While VacuumFailSafeActive is reset to false before calling this, we
@@ -735,14 +735,14 @@ heap_vacuum_rel(Relation rel, const VacuumParams params,
 	vacrel->consider_bypass_optimization = true;
 	vacrel->do_index_vacuuming = true;
 	vacrel->do_index_cleanup = true;
-	vacrel->do_rel_truncate = (params.truncate != VACOPTVALUE_DISABLED);
-	if (params.index_cleanup == VACOPTVALUE_DISABLED)
+	vacrel->do_rel_truncate = (params->truncate != VACOPTVALUE_DISABLED);
+	if (params->index_cleanup == VACOPTVALUE_DISABLED)
 	{
 		/* Force disable index vacuuming up-front */
 		vacrel->do_index_vacuuming = false;
 		vacrel->do_index_cleanup = false;
 	}
-	else if (params.index_cleanup == VACOPTVALUE_ENABLED)
+	else if (params->index_cleanup == VACOPTVALUE_ENABLED)
 	{
 		/* Force index vacuuming.  Note that failsafe can still bypass. */
 		vacrel->consider_bypass_optimization = false;
@@ -750,7 +750,7 @@ heap_vacuum_rel(Relation rel, const VacuumParams params,
 	else
 	{
 		/* Default/auto, make all decisions dynamically */
-		Assert(params.index_cleanup == VACOPTVALUE_AUTO);
+		Assert(params->index_cleanup == VACOPTVALUE_AUTO);
 	}
 
 	/* Initialize page counters explicitly (be tidy) */
@@ -820,7 +820,7 @@ heap_vacuum_rel(Relation rel, const VacuumParams params,
 	 */
 	vacrel->skippedallvis = false;
 	skipwithvm = true;
-	if (params.options & VACOPT_DISABLE_PAGE_SKIPPING)
+	if (params->options & VACOPT_DISABLE_PAGE_SKIPPING)
 	{
 		/*
 		 * Force aggressive mode, and disable skipping blocks using the
@@ -867,7 +867,7 @@ heap_vacuum_rel(Relation rel, const VacuumParams params,
 	 * is already dangerously old.)
 	 */
 	lazy_check_wraparound_failsafe(vacrel);
-	dead_items_alloc(vacrel, params.nworkers);
+	dead_items_alloc(vacrel, params->nworkers);
 
 	/*
 	 * Call lazy_scan_heap to perform all required heap pruning, index
@@ -991,9 +991,9 @@ heap_vacuum_rel(Relation rel, const VacuumParams params,
 	{
 		TimestampTz endtime = GetCurrentTimestamp();
 
-		if (verbose || params.log_vacuum_min_duration == 0 ||
+		if (verbose || params->log_vacuum_min_duration == 0 ||
 			TimestampDifferenceExceeds(starttime, endtime,
-									   params.log_vacuum_min_duration))
+									   params->log_vacuum_min_duration))
 		{
 			long		secs_dur;
 			int			usecs_dur;
@@ -1028,10 +1028,10 @@ heap_vacuum_rel(Relation rel, const VacuumParams params,
 				 * Aggressiveness already reported earlier, in dedicated
 				 * VACUUM VERBOSE ereport
 				 */
-				Assert(!params.is_wraparound);
+				Assert(!params->is_wraparound);
 				msgfmt = _("finished vacuuming \"%s.%s.%s\": index scans: %d\n");
 			}
-			else if (params.is_wraparound)
+			else if (params->is_wraparound)
 			{
 				/*
 				 * While it's possible for a VACUUM to be both is_wraparound
diff --git a/src/backend/catalog/toasting.c b/src/backend/catalog/toasting.c
index 078a1cf5127..4aa52a4bd25 100644
--- a/src/backend/catalog/toasting.c
+++ b/src/backend/catalog/toasting.c
@@ -14,6 +14,7 @@
  */
 #include "postgres.h"
 
+#include "access/genam.h"
 #include "access/heapam.h"
 #include "access/toast_compression.h"
 #include "access/xact.h"
diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c
index eeed91be266..49a5cdf579c 100644
--- a/src/backend/commands/analyze.c
+++ b/src/backend/commands/analyze.c
@@ -76,7 +76,7 @@ static BufferAccessStrategy vac_strategy;
 
 
 static void do_analyze_rel(Relation onerel,
-						   const VacuumParams params, List *va_cols,
+						   const VacuumParams *params, List *va_cols,
 						   AcquireSampleRowsFunc acquirefunc, BlockNumber relpages,
 						   bool inh, bool in_outer_xact, int elevel);
 static void compute_index_stats(Relation onerel, double totalrows,
@@ -107,7 +107,7 @@ static Datum ind_fetch_func(VacAttrStatsP stats, int rownum, bool *isNull);
  */
 void
 analyze_rel(Oid relid, RangeVar *relation,
-			const VacuumParams params, List *va_cols, bool in_outer_xact,
+			const VacuumParams *params, List *va_cols, bool in_outer_xact,
 			BufferAccessStrategy bstrategy)
 {
 	Relation	onerel;
@@ -116,7 +116,7 @@ analyze_rel(Oid relid, RangeVar *relation,
 	BlockNumber relpages = 0;
 
 	/* Select logging level */
-	if (params.options & VACOPT_VERBOSE)
+	if (params->options & VACOPT_VERBOSE)
 		elevel = INFO;
 	else
 		elevel = DEBUG2;
@@ -138,8 +138,8 @@ analyze_rel(Oid relid, RangeVar *relation,
 	 *
 	 * Make sure to generate only logs for ANALYZE in this case.
 	 */
-	onerel = vacuum_open_relation(relid, relation, params.options & ~(VACOPT_VACUUM),
-								  params.log_analyze_min_duration >= 0,
+	onerel = vacuum_open_relation(relid, relation, params->options & ~(VACOPT_VACUUM),
+								  params->log_analyze_min_duration >= 0,
 								  ShareUpdateExclusiveLock);
 
 	/* leave if relation could not be opened or locked */
@@ -155,7 +155,7 @@ analyze_rel(Oid relid, RangeVar *relation,
 	 */
 	if (!vacuum_is_permitted_for_relation(RelationGetRelid(onerel),
 										  onerel->rd_rel,
-										  params.options & ~VACOPT_VACUUM))
+										  params->options & ~VACOPT_VACUUM))
 	{
 		relation_close(onerel, ShareUpdateExclusiveLock);
 		return;
@@ -227,7 +227,7 @@ analyze_rel(Oid relid, RangeVar *relation,
 	else
 	{
 		/* No need for a WARNING if we already complained during VACUUM */
-		if (!(params.options & VACOPT_VACUUM))
+		if (!(params->options & VACOPT_VACUUM))
 			ereport(WARNING,
 					(errmsg("skipping \"%s\" --- cannot analyze non-tables or special system tables",
 							RelationGetRelationName(onerel))));
@@ -281,7 +281,7 @@ analyze_rel(Oid relid, RangeVar *relation,
  * appropriate acquirefunc for each child table.
  */
 static void
-do_analyze_rel(Relation onerel, const VacuumParams params,
+do_analyze_rel(Relation onerel, const VacuumParams *params,
 			   List *va_cols, AcquireSampleRowsFunc acquirefunc,
 			   BlockNumber relpages, bool inh, bool in_outer_xact,
 			   int elevel)
@@ -315,9 +315,9 @@ do_analyze_rel(Relation onerel, const VacuumParams params,
 	PgStat_Counter startreadtime = 0;
 	PgStat_Counter startwritetime = 0;
 
-	verbose = (params.options & VACOPT_VERBOSE) != 0;
+	verbose = (params->options & VACOPT_VERBOSE) != 0;
 	instrument = (verbose || (AmAutoVacuumWorkerProcess() &&
-							  params.log_analyze_min_duration >= 0));
+							  params->log_analyze_min_duration >= 0));
 	if (inh)
 		ereport(elevel,
 				(errmsg("analyzing \"%s.%s\" inheritance tree",
@@ -712,7 +712,7 @@ do_analyze_rel(Relation onerel, const VacuumParams params,
 	 * amvacuumcleanup() when called in ANALYZE-only mode.  The only exception
 	 * among core index AMs is GIN/ginvacuumcleanup().
 	 */
-	if (!(params.options & VACOPT_VACUUM))
+	if (!(params->options & VACOPT_VACUUM))
 	{
 		for (ind = 0; ind < nindexes; ind++)
 		{
@@ -742,9 +742,9 @@ do_analyze_rel(Relation onerel, const VacuumParams params,
 	{
 		TimestampTz endtime = GetCurrentTimestamp();
 
-		if (verbose || params.log_analyze_min_duration == 0 ||
+		if (verbose || params->log_analyze_min_duration == 0 ||
 			TimestampDifferenceExceeds(starttime, endtime,
-									   params.log_analyze_min_duration))
+									   params->log_analyze_min_duration))
 		{
 			long		delay_in_ms;
 			WalUsage	walusage;
diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c
index 09066db0956..f241e18b153 100644
--- a/src/backend/commands/cluster.c
+++ b/src/backend/commands/cluster.c
@@ -927,7 +927,7 @@ copy_table_data(Relation NewHeap, Relation OldHeap, Relation OldIndex, bool verb
 	 * not to be aggressive about this.
 	 */
 	memset(&params, 0, sizeof(VacuumParams));
-	vacuum_get_cutoffs(OldHeap, params, &cutoffs);
+	vacuum_get_cutoffs(OldHeap, &params, &cutoffs);
 
 	/*
 	 * FreezeXid will become the table's new relfrozenxid, and that mustn't go
@@ -1950,7 +1950,7 @@ process_single_relation(RepackStmt *stmt, ClusterParams *params)
 			vac_params.options |= VACOPT_ANALYZE;
 			if (params->options & CLUOPT_VERBOSE)
 				vac_params.options |= VACOPT_VERBOSE;
-			analyze_rel(tableOid, NULL, vac_params,
+			analyze_rel(tableOid, NULL, &vac_params,
 						stmt->relation->va_cols, true, NULL);
 			PopActiveSnapshot();
 			CommandCounterIncrement();
diff --git a/src/backend/commands/event_trigger.c b/src/backend/commands/event_trigger.c
index ecd2e929f8d..dcd2f5a09bb 100644
--- a/src/backend/commands/event_trigger.c
+++ b/src/backend/commands/event_trigger.c
@@ -13,6 +13,7 @@
  */
 #include "postgres.h"
 
+#include "access/genam.h"
 #include "access/heapam.h"
 #include "access/htup_details.h"
 #include "access/table.h"
diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index bce3a2daa24..b0e2883499a 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -126,7 +126,7 @@ static void vac_truncate_clog(TransactionId frozenXID,
 							  MultiXactId minMulti,
 							  TransactionId lastSaneFrozenXid,
 							  MultiXactId lastSaneMinMulti);
-static bool vacuum_rel(Oid relid, RangeVar *relation, VacuumParams params,
+static bool vacuum_rel(Oid relid, RangeVar *relation, const VacuumParams *params,
 					   BufferAccessStrategy bstrategy);
 static double compute_parallel_delay(void);
 static VacOptValue get_vacoptval_from_boolean(DefElem *def);
@@ -462,7 +462,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 	}
 
 	/* Now go through the common routine */
-	vacuum(vacstmt->rels, params, bstrategy, vac_context, isTopLevel);
+	vacuum(vacstmt->rels, &params, bstrategy, vac_context, isTopLevel);
 
 	/* Finally, clean up the vacuum memory context */
 	MemoryContextDelete(vac_context);
@@ -491,7 +491,7 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
  * memory context that will not disappear at transaction commit.
  */
 void
-vacuum(List *relations, const VacuumParams params, BufferAccessStrategy bstrategy,
+vacuum(List *relations, const VacuumParams *params, BufferAccessStrategy bstrategy,
 	   MemoryContext vac_context, bool isTopLevel)
 {
 	static bool in_vacuum = false;
@@ -500,7 +500,7 @@ vacuum(List *relations, const VacuumParams params, BufferAccessStrategy bstrateg
 	volatile bool in_outer_xact,
 				use_own_xacts;
 
-	stmttype = (params.options & VACOPT_VACUUM) ? "VACUUM" : "ANALYZE";
+	stmttype = (params->options & VACOPT_VACUUM) ? "VACUUM" : "ANALYZE";
 
 	/*
 	 * We cannot run VACUUM inside a user transaction block; if we were inside
@@ -510,7 +510,7 @@ vacuum(List *relations, const VacuumParams params, BufferAccessStrategy bstrateg
 	 *
 	 * ANALYZE (without VACUUM) can run either way.
 	 */
-	if (params.options & VACOPT_VACUUM)
+	if (params->options & VACOPT_VACUUM)
 	{
 		PreventInTransactionBlock(isTopLevel, stmttype);
 		in_outer_xact = false;
@@ -533,7 +533,7 @@ vacuum(List *relations, const VacuumParams params, BufferAccessStrategy bstrateg
 	 * Build list of relation(s) to process, putting any new data in
 	 * vac_context for safekeeping.
 	 */
-	if (params.options & VACOPT_ONLY_DATABASE_STATS)
+	if (params->options & VACOPT_ONLY_DATABASE_STATS)
 	{
 		/* We don't process any tables in this case */
 		Assert(relations == NIL);
@@ -549,7 +549,7 @@ vacuum(List *relations, const VacuumParams params, BufferAccessStrategy bstrateg
 			List	   *sublist;
 			MemoryContext old_context;
 
-			sublist = expand_vacuum_rel(vrel, vac_context, params.options);
+			sublist = expand_vacuum_rel(vrel, vac_context, params->options);
 			old_context = MemoryContextSwitchTo(vac_context);
 			newrels = list_concat(newrels, sublist);
 			MemoryContextSwitchTo(old_context);
@@ -557,7 +557,7 @@ vacuum(List *relations, const VacuumParams params, BufferAccessStrategy bstrateg
 		relations = newrels;
 	}
 	else
-		relations = get_all_vacuum_rels(vac_context, params.options);
+		relations = get_all_vacuum_rels(vac_context, params->options);
 
 	/*
 	 * Decide whether we need to start/commit our own transactions.
@@ -573,11 +573,11 @@ vacuum(List *relations, const VacuumParams params, BufferAccessStrategy bstrateg
 	 * transaction block, and also in an autovacuum worker, use own
 	 * transactions so we can release locks sooner.
 	 */
-	if (params.options & VACOPT_VACUUM)
+	if (params->options & VACOPT_VACUUM)
 		use_own_xacts = true;
 	else
 	{
-		Assert(params.options & VACOPT_ANALYZE);
+		Assert(params->options & VACOPT_ANALYZE);
 		if (AmAutoVacuumWorkerProcess())
 			use_own_xacts = true;
 		else if (in_outer_xact)
@@ -628,13 +628,13 @@ vacuum(List *relations, const VacuumParams params, BufferAccessStrategy bstrateg
 		{
 			VacuumRelation *vrel = lfirst_node(VacuumRelation, cur);
 
-			if (params.options & VACOPT_VACUUM)
+			if (params->options & VACOPT_VACUUM)
 			{
 				if (!vacuum_rel(vrel->oid, vrel->relation, params, bstrategy))
 					continue;
 			}
 
-			if (params.options & VACOPT_ANALYZE)
+			if (params->options & VACOPT_ANALYZE)
 			{
 				/*
 				 * If using separate xacts, start one for analyze. Otherwise,
@@ -698,8 +698,8 @@ vacuum(List *relations, const VacuumParams params, BufferAccessStrategy bstrateg
 		StartTransactionCommand();
 	}
 
-	if ((params.options & VACOPT_VACUUM) &&
-		!(params.options & VACOPT_SKIP_DATABASE_STATS))
+	if ((params->options & VACOPT_VACUUM) &&
+		!(params->options & VACOPT_SKIP_DATABASE_STATS))
 	{
 		/*
 		 * Update pg_database.datfrozenxid, and truncate pg_xact if possible.
@@ -1097,7 +1097,7 @@ get_all_vacuum_rels(MemoryContext vac_context, int options)
  * minimum).
  */
 bool
-vacuum_get_cutoffs(Relation rel, const VacuumParams params,
+vacuum_get_cutoffs(Relation rel, const VacuumParams *params,
 				   struct VacuumCutoffs *cutoffs)
 {
 	int			freeze_min_age,
@@ -1113,10 +1113,10 @@ vacuum_get_cutoffs(Relation rel, const VacuumParams params,
 				aggressiveMXIDCutoff;
 
 	/* Use mutable copies of freeze age parameters */
-	freeze_min_age = params.freeze_min_age;
-	multixact_freeze_min_age = params.multixact_freeze_min_age;
-	freeze_table_age = params.freeze_table_age;
-	multixact_freeze_table_age = params.multixact_freeze_table_age;
+	freeze_min_age = params->freeze_min_age;
+	multixact_freeze_min_age = params->multixact_freeze_min_age;
+	freeze_table_age = params->freeze_table_age;
+	multixact_freeze_table_age = params->multixact_freeze_table_age;
 
 	/* Set pg_class fields in cutoffs */
 	cutoffs->relfrozenxid = rel->rd_rel->relfrozenxid;
@@ -2003,7 +2003,7 @@ vac_truncate_clog(TransactionId frozenXID,
  *		At entry and exit, we are not inside a transaction.
  */
 static bool
-vacuum_rel(Oid relid, RangeVar *relation, VacuumParams params,
+vacuum_rel(Oid relid, RangeVar *relation, const VacuumParams *params,
 		   BufferAccessStrategy bstrategy)
 {
 	LOCKMODE	lmode;
@@ -2014,18 +2014,21 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams params,
 	Oid			save_userid;
 	int			save_sec_context;
 	int			save_nestlevel;
+	VacuumParams params_copy;
 	VacuumParams toast_vacuum_params;
 
 	/*
 	 * This function scribbles on the parameters, so make a copy early to
-	 * avoid affecting the TOAST table (if we do end up recursing to it).
+	 * avoid affecting the TOAST table (if we do end up recursing to it) or
+	 * other relations in the same VACUUM command.
 	 */
-	memcpy(&toast_vacuum_params, &params, sizeof(VacuumParams));
+	memcpy(&params_copy, params, sizeof(VacuumParams));
+	memcpy(&toast_vacuum_params, params, sizeof(VacuumParams));
 
 	/* Begin a transaction for vacuuming this relation */
 	StartTransactionCommand();
 
-	if (!(params.options & VACOPT_FULL))
+	if (!(params->options & VACOPT_FULL))
 	{
 		/*
 		 * In lazy vacuum, we can set the PROC_IN_VACUUM flag, which lets
@@ -2051,7 +2054,7 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams params,
 		 */
 		LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
 		MyProc->statusFlags |= PROC_IN_VACUUM;
-		if (params.is_wraparound)
+		if (params->is_wraparound)
 			MyProc->statusFlags |= PROC_VACUUM_FOR_WRAPAROUND;
 		ProcGlobal->statusFlags[MyProc->pgxactoff] = MyProc->statusFlags;
 		LWLockRelease(ProcArrayLock);
@@ -2075,12 +2078,12 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams params,
 	 * vacuum, but just ShareUpdateExclusiveLock for concurrent vacuum. Either
 	 * way, we can be sure that no other backend is vacuuming the same table.
 	 */
-	lmode = (params.options & VACOPT_FULL) ?
+	lmode = (params->options & VACOPT_FULL) ?
 		AccessExclusiveLock : ShareUpdateExclusiveLock;
 
 	/* open the relation and get the appropriate lock on it */
-	rel = vacuum_open_relation(relid, relation, params.options,
-							   params.log_vacuum_min_duration >= 0, lmode);
+	rel = vacuum_open_relation(relid, relation, params->options,
+							   params->log_vacuum_min_duration >= 0, lmode);
 
 	/* leave if relation could not be opened or locked */
 	if (!rel)
@@ -2095,8 +2098,8 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams params,
 	 * This is only safe to do because we hold a session lock on the main
 	 * relation that prevents concurrent deletion.
 	 */
-	if (OidIsValid(params.toast_parent))
-		priv_relid = params.toast_parent;
+	if (OidIsValid(params->toast_parent))
+		priv_relid = params->toast_parent;
 	else
 		priv_relid = RelationGetRelid(rel);
 
@@ -2109,7 +2112,7 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams params,
 	 */
 	if (!vacuum_is_permitted_for_relation(priv_relid,
 										  rel->rd_rel,
-										  params.options & ~VACOPT_ANALYZE))
+										  params->options & ~VACOPT_ANALYZE))
 	{
 		relation_close(rel, lmode);
 		PopActiveSnapshot();
@@ -2180,7 +2183,7 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams params,
 	 * Set index_cleanup option based on index_cleanup reloption if it wasn't
 	 * specified in VACUUM command, or when running in an autovacuum worker
 	 */
-	if (params.index_cleanup == VACOPTVALUE_UNSPECIFIED)
+	if (params->index_cleanup == VACOPTVALUE_UNSPECIFIED)
 	{
 		StdRdOptIndexCleanup vacuum_index_cleanup;
 
@@ -2191,23 +2194,23 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams params,
 				((StdRdOptions *) rel->rd_options)->vacuum_index_cleanup;
 
 		if (vacuum_index_cleanup == STDRD_OPTION_VACUUM_INDEX_CLEANUP_AUTO)
-			params.index_cleanup = VACOPTVALUE_AUTO;
+			params_copy.index_cleanup = VACOPTVALUE_AUTO;
 		else if (vacuum_index_cleanup == STDRD_OPTION_VACUUM_INDEX_CLEANUP_ON)
-			params.index_cleanup = VACOPTVALUE_ENABLED;
+			params_copy.index_cleanup = VACOPTVALUE_ENABLED;
 		else
 		{
 			Assert(vacuum_index_cleanup ==
 				   STDRD_OPTION_VACUUM_INDEX_CLEANUP_OFF);
-			params.index_cleanup = VACOPTVALUE_DISABLED;
+			params_copy.index_cleanup = VACOPTVALUE_DISABLED;
 		}
 	}
 
 #ifdef USE_INJECTION_POINTS
-	if (params.index_cleanup == VACOPTVALUE_AUTO)
+	if (params_copy.index_cleanup == VACOPTVALUE_AUTO)
 		INJECTION_POINT("vacuum-index-cleanup-auto", NULL);
-	else if (params.index_cleanup == VACOPTVALUE_DISABLED)
+	else if (params_copy.index_cleanup == VACOPTVALUE_DISABLED)
 		INJECTION_POINT("vacuum-index-cleanup-disabled", NULL);
-	else if (params.index_cleanup == VACOPTVALUE_ENABLED)
+	else if (params_copy.index_cleanup == VACOPTVALUE_ENABLED)
 		INJECTION_POINT("vacuum-index-cleanup-enabled", NULL);
 #endif
 
@@ -2217,36 +2220,36 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams params,
 	 */
 	if (rel->rd_options != NULL &&
 		((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate >= 0)
-		params.max_eager_freeze_failure_rate =
+		params_copy.max_eager_freeze_failure_rate =
 			((StdRdOptions *) rel->rd_options)->vacuum_max_eager_freeze_failure_rate;
 
 	/*
 	 * Set truncate option based on truncate reloption or GUC if it wasn't
 	 * specified in VACUUM command, or when running in an autovacuum worker
 	 */
-	if (params.truncate == VACOPTVALUE_UNSPECIFIED)
+	if (params->truncate == VACOPTVALUE_UNSPECIFIED)
 	{
 		StdRdOptions *opts = (StdRdOptions *) rel->rd_options;
 
 		if (opts && opts->vacuum_truncate != PG_TERNARY_UNSET)
 		{
 			if (opts->vacuum_truncate == PG_TERNARY_TRUE)
-				params.truncate = VACOPTVALUE_ENABLED;
+				params_copy.truncate = VACOPTVALUE_ENABLED;
 			else
-				params.truncate = VACOPTVALUE_DISABLED;
+				params_copy.truncate = VACOPTVALUE_DISABLED;
 		}
 		else if (vacuum_truncate)
-			params.truncate = VACOPTVALUE_ENABLED;
+			params_copy.truncate = VACOPTVALUE_ENABLED;
 		else
-			params.truncate = VACOPTVALUE_DISABLED;
+			params_copy.truncate = VACOPTVALUE_DISABLED;
 	}
 
 #ifdef USE_INJECTION_POINTS
-	if (params.truncate == VACOPTVALUE_AUTO)
+	if (params_copy.truncate == VACOPTVALUE_AUTO)
 		INJECTION_POINT("vacuum-truncate-auto", NULL);
-	else if (params.truncate == VACOPTVALUE_DISABLED)
+	else if (params_copy.truncate == VACOPTVALUE_DISABLED)
 		INJECTION_POINT("vacuum-truncate-disabled", NULL);
-	else if (params.truncate == VACOPTVALUE_ENABLED)
+	else if (params_copy.truncate == VACOPTVALUE_ENABLED)
 		INJECTION_POINT("vacuum-truncate-enabled", NULL);
 #endif
 
@@ -2256,9 +2259,9 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams params,
 	 * automatically rebuilt by cluster_rel so we shouldn't recurse to it,
 	 * unless PROCESS_MAIN is disabled.
 	 */
-	if ((params.options & VACOPT_PROCESS_TOAST) != 0 &&
-		((params.options & VACOPT_FULL) == 0 ||
-		 (params.options & VACOPT_PROCESS_MAIN) == 0))
+	if ((params->options & VACOPT_PROCESS_TOAST) != 0 &&
+		((params->options & VACOPT_FULL) == 0 ||
+		 (params->options & VACOPT_PROCESS_MAIN) == 0))
 		toast_relid = rel->rd_rel->reltoastrelid;
 	else
 		toast_relid = InvalidOid;
@@ -2281,16 +2284,16 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams params,
 	 * table is required (e.g., PROCESS_TOAST is set), we force PROCESS_MAIN
 	 * to be set when we recurse to the TOAST table.
 	 */
-	if (params.options & VACOPT_PROCESS_MAIN)
+	if (params->options & VACOPT_PROCESS_MAIN)
 	{
 		/*
 		 * Do the actual work --- either FULL or "lazy" vacuum
 		 */
-		if (params.options & VACOPT_FULL)
+		if (params->options & VACOPT_FULL)
 		{
 			ClusterParams cluster_params = {0};
 
-			if ((params.options & VACOPT_VERBOSE) != 0)
+			if ((params->options & VACOPT_VERBOSE) != 0)
 				cluster_params.options |= CLUOPT_VERBOSE;
 
 			/* VACUUM FULL is a variant of REPACK; see cluster.c */
@@ -2301,7 +2304,7 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams params,
 			rel = NULL;
 		}
 		else
-			table_relation_vacuum(rel, params, bstrategy);
+			table_relation_vacuum(rel, &params_copy, bstrategy);
 	}
 
 	/* Roll back any GUC changes executed by index functions */
@@ -2338,7 +2341,7 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams params,
 		toast_vacuum_params.options |= VACOPT_PROCESS_MAIN;
 		toast_vacuum_params.toast_parent = relid;
 
-		vacuum_rel(toast_relid, NULL, toast_vacuum_params, bstrategy);
+		vacuum_rel(toast_relid, NULL, &toast_vacuum_params, bstrategy);
 	}
 
 	/*
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index 219673db930..bd71fc6bf24 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -3197,7 +3197,7 @@ autovacuum_do_vac_analyze(autovac_table *tab, BufferAccessStrategy bstrategy)
 	rel_list = list_make1(rel);
 	MemoryContextSwitchTo(old_context);
 
-	vacuum(rel_list, tab->at_params, bstrategy, vac_context, true);
+	vacuum(rel_list, &tab->at_params, bstrategy, vac_context, true);
 
 	MemoryContextDelete(vac_context);
 }
diff --git a/src/backend/replication/logical/conflict.c b/src/backend/replication/logical/conflict.c
index ca71a81c7bf..5e3f8e69e93 100644
--- a/src/backend/replication/logical/conflict.c
+++ b/src/backend/replication/logical/conflict.c
@@ -15,6 +15,7 @@
 #include "postgres.h"
 
 #include "access/commit_ts.h"
+#include "access/genam.h"
 #include "access/tableam.h"
 #include "executor/executor.h"
 #include "pgstat.h"
diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c
index 2d7708805a6..339b777d09b 100644
--- a/src/backend/replication/logical/worker.c
+++ b/src/backend/replication/logical/worker.c
@@ -247,6 +247,7 @@
 #include <sys/stat.h>
 #include <unistd.h>
 
+#include "access/genam.h"
 #include "access/commit_ts.h"
 #include "access/table.h"
 #include "access/tableam.h"
diff --git a/src/backend/utils/adt/ri_triggers.c b/src/backend/utils/adt/ri_triggers.c
index d22b8ef7f3c..c20c550057c 100644
--- a/src/backend/utils/adt/ri_triggers.c
+++ b/src/backend/utils/adt/ri_triggers.c
@@ -42,6 +42,7 @@
 #include "utils/datum.h"
 #include "utils/fmgroids.h"
 #include "utils/guc.h"
+#include "utils/hsearch.h"
 #include "utils/inval.h"
 #include "utils/lsyscache.h"
 #include "utils/memutils.h"
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 305ecc31a9e..2096bd1aac5 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -21,7 +21,6 @@
 #include "access/skey.h"
 #include "access/table.h"		/* for backward compatibility */
 #include "access/tableam.h"
-#include "commands/vacuum.h"
 #include "nodes/lockoptions.h"
 #include "nodes/primnodes.h"
 #include "storage/bufpage.h"
@@ -47,7 +46,8 @@
 typedef struct BulkInsertStateData *BulkInsertState;
 typedef struct GlobalVisState GlobalVisState;
 typedef struct TupleTableSlot TupleTableSlot;
-struct VacuumCutoffs;
+typedef struct VacuumCutoffs VacuumCutoffs;
+typedef struct VacuumParams VacuumParams;
 
 #define MaxLockTupleMode	LockTupleExclusive
 
@@ -299,7 +299,7 @@ typedef struct PruneFreezeParams
 	 * HEAPTUPLE_DEAD. Currently only vacuum passes in cutoffs. Vacuum
 	 * calculates them once, at the beginning of vacuuming the relation.
 	 */
-	struct VacuumCutoffs *cutoffs;
+	VacuumCutoffs *cutoffs;
 } PruneFreezeParams;
 
 /*
@@ -421,7 +421,7 @@ extern void heap_inplace_update_and_unlock(Relation relation,
 extern void heap_inplace_unlock(Relation relation,
 								HeapTuple oldtup, Buffer buffer);
 extern bool heap_prepare_freeze_tuple(HeapTupleHeader tuple,
-									  const struct VacuumCutoffs *cutoffs,
+									  const VacuumCutoffs * cutoffs,
 									  HeapPageFreeze *pagefrz,
 									  HeapTupleFreeze *frz, bool *totally_frozen);
 
@@ -433,7 +433,7 @@ extern bool heap_freeze_tuple(HeapTupleHeader tuple,
 							  TransactionId relfrozenxid, TransactionId relminmxid,
 							  TransactionId FreezeLimit, TransactionId MultiXactCutoff);
 extern bool heap_tuple_should_freeze(HeapTupleHeader tuple,
-									 const struct VacuumCutoffs *cutoffs,
+									 const VacuumCutoffs * cutoffs,
 									 TransactionId *NoFreezePageRelfrozenXid,
 									 MultiXactId *NoFreezePageRelminMxid);
 extern bool heap_tuple_needs_eventual_freeze(HeapTupleHeader tuple);
@@ -471,7 +471,7 @@ extern void log_heap_prune_and_freeze(Relation relation, Buffer buffer,
 
 /* in heap/vacuumlazy.c */
 extern void heap_vacuum_rel(Relation rel,
-							const VacuumParams params, BufferAccessStrategy bstrategy);
+							const VacuumParams *params, BufferAccessStrategy bstrategy);
 
 /* in heap/heapam_visibility.c */
 extern bool HeapTupleSatisfiesVisibility(HeapTuple htup, Snapshot snapshot,
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 06084752245..4b7cbd41199 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -20,7 +20,6 @@
 #include "access/relscan.h"
 #include "access/sdir.h"
 #include "access/xact.h"
-#include "commands/vacuum.h"
 #include "executor/tuptable.h"
 #include "storage/read_stream.h"
 #include "utils/rel.h"
@@ -38,7 +37,9 @@ extern PGDLLIMPORT bool synchronize_seqscans;
 typedef struct BulkInsertStateData BulkInsertStateData;
 typedef struct IndexInfo IndexInfo;
 typedef struct SampleScanState SampleScanState;
+typedef struct ScanKeyData ScanKeyData;
 typedef struct ValidateIndexState ValidateIndexState;
+typedef struct VacuumParams VacuumParams;
 
 /*
  * Bitmask values for the flags argument to the scan_begin callback.
@@ -651,7 +652,7 @@ typedef struct TableAmRoutine
 	 * integrate with autovacuum's scheduling.
 	 */
 	void		(*relation_vacuum) (Relation rel,
-									const VacuumParams params,
+									const VacuumParams *params,
 									BufferAccessStrategy bstrategy);
 
 	/*
@@ -1694,7 +1695,7 @@ table_relation_copy_for_cluster(Relation OldTable, Relation NewTable,
  * routine, even if (for ANALYZE) it is part of the same VACUUM command.
  */
 static inline void
-table_relation_vacuum(Relation rel, const VacuumParams params,
+table_relation_vacuum(Relation rel, const VacuumParams *params,
 					  BufferAccessStrategy bstrategy)
 {
 	rel->rd_tableam->relation_vacuum(rel, params, bstrategy);
diff --git a/src/include/commands/vacuum.h b/src/include/commands/vacuum.h
index 1f45bca015c..ef304e33078 100644
--- a/src/include/commands/vacuum.h
+++ b/src/include/commands/vacuum.h
@@ -362,7 +362,7 @@ extern PGDLLIMPORT int64 parallel_vacuum_worker_delay_ns;
 
 /* in commands/vacuum.c */
 extern void ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel);
-extern void vacuum(List *relations, const VacuumParams params,
+extern void vacuum(List *relations, const VacuumParams *params,
 				   BufferAccessStrategy bstrategy, MemoryContext vac_context,
 				   bool isTopLevel);
 extern void vac_open_indexes(Relation relation, LOCKMODE lockmode,
@@ -383,7 +383,7 @@ extern void vac_update_relstats(Relation relation,
 								bool *frozenxid_updated,
 								bool *minmulti_updated,
 								bool in_outer_xact);
-extern bool vacuum_get_cutoffs(Relation rel, const VacuumParams params,
+extern bool vacuum_get_cutoffs(Relation rel, const VacuumParams *params,
 							   struct VacuumCutoffs *cutoffs);
 extern bool vacuum_xid_failsafe_check(const struct VacuumCutoffs *cutoffs);
 extern void vac_update_datfrozenxid(void);
@@ -426,7 +426,7 @@ extern void parallel_vacuum_main(dsm_segment *seg, shm_toc *toc);
 
 /* in commands/analyze.c */
 extern void analyze_rel(Oid relid, RangeVar *relation,
-						const VacuumParams params, List *va_cols, bool in_outer_xact,
+						const VacuumParams *params, List *va_cols, bool in_outer_xact,
 						BufferAccessStrategy bstrategy);
 extern bool std_typanalyze(VacAttrStats *stats);
 
diff --git a/src/pl/tcl/pltcl.c b/src/pl/tcl/pltcl.c
index 44491de669a..85e83bbf1e3 100644
--- a/src/pl/tcl/pltcl.c
+++ b/src/pl/tcl/pltcl.c
@@ -31,6 +31,7 @@
 #include "utils/acl.h"
 #include "utils/builtins.h"
 #include "utils/guc.h"
+#include "utils/hsearch.h"
 #include "utils/lsyscache.h"
 #include "utils/memutils.h"
 #include "utils/regproc.h"
-- 
2.50.1 (Apple Git-155)

