From 043fe55dde07e12c0c21aab5b3d5f4fc412d2b38 Mon Sep 17 00:00:00 2001
From: Corey Huinker <corey.huinker@gmail.com>
Date: Mon, 3 Aug 2026 02:13:14 -0400
Subject: [PATCH v3 11/15] Swtich internal statistics update functions to using
 named parameters.

This modifies the pattern of the the *_statistics_update_internal()
functions to stop using arrays of NullableDatum in favor of using
multiple NullableDatum parameters. This makes the code more maintainable
in that we do not need to have two arrays of StatsArgInfo, one with all
of the parameters from the SQL function and another more abbreviated
list used by the internal import_* function, as the index names would
likely be very similar between the two sets thus making subtle bugs more
likely. Additionally, any new stats automatically mean new parameters to
the *update_internal() functions, whereas an array parameter would not
detect that the caller didn't provide a big-enough array.
---
 src/backend/statistics/attribute_stats.c      | 171 ++++++++++--------
 src/backend/statistics/extended_stats_funcs.c |   5 +
 src/backend/statistics/relation_stats.c       | 136 +++++++-------
 3 files changed, 174 insertions(+), 138 deletions(-)

diff --git a/src/backend/statistics/attribute_stats.c b/src/backend/statistics/attribute_stats.c
index d053d91e5dc..08d294607ac 100644
--- a/src/backend/statistics/attribute_stats.c
+++ b/src/backend/statistics/attribute_stats.c
@@ -39,10 +39,10 @@ enum attribute_stats_argnum
 {
 	ATTARG_ATTRELSCHEMA = 0,
 	ATTARG_ATTRELNAME,
-	ATTARG_VERSION,
 	ATTARG_ATTNAME,
 	ATTARG_ATTNUM,
 	ATTARG_INHERITED,
+	ATTARG_VERSION,
 	ATTARG_NULL_FRAC,
 	ATTARG_AVG_WIDTH,
 	ATTARG_N_DISTINCT,
@@ -63,10 +63,10 @@ static struct StatsArgInfo attarginfo[] =
 {
 	[ATTARG_ATTRELSCHEMA] = {"schemaname", TEXTOID},
 	[ATTARG_ATTRELNAME] = {"relname", TEXTOID},
-	[ATTARG_VERSION] = {"version", INT4OID},
 	[ATTARG_ATTNAME] = {"attname", TEXTOID},
 	[ATTARG_ATTNUM] = {"attnum", INT2OID},
 	[ATTARG_INHERITED] = {"inherited", BOOLOID},
+	[ATTARG_VERSION] = {"version", INT4OID},
 	[ATTARG_NULL_FRAC] = {"null_frac", FLOAT4OID},
 	[ATTARG_AVG_WIDTH] = {"avg_width", INT4OID},
 	[ATTARG_N_DISTINCT] = {"n_distinct", FLOAT4OID},
@@ -111,7 +111,20 @@ static bool attribute_statistics_update_internal(Oid reloid,
 												 const char *attname,
 												 AttrNumber attnum,
 												 bool inherited,
-												 const NullableDatum *args);
+												 const NullableDatum *version,
+												 const NullableDatum *null_frac,
+												 const NullableDatum *avg_width,
+												 const NullableDatum *n_distinct,
+												 const NullableDatum *most_common_vals,
+												 const NullableDatum *most_common_freqs,
+												 const NullableDatum *histogram_bounds,
+												 const NullableDatum *correlation,
+												 const NullableDatum *most_common_elems,
+												 const NullableDatum *most_common_elem_freqs,
+												 const NullableDatum *elem_count_histogram,
+												 const NullableDatum *range_length_histogram,
+												 const NullableDatum *range_empty_frac,
+												 const NullableDatum *range_bounds_histogram);
 static void upsert_pg_statistic(Relation starel, HeapTuple oldtup,
 								const Datum *values, const bool *nulls, const bool *replaces);
 static bool delete_pg_statistic(Oid reloid, AttrNumber attnum, bool stainherit);
@@ -207,7 +220,22 @@ attribute_statistics_update(const NullableDatum *args)
 	inherited = DatumGetBool(args[ATTARG_INHERITED].value);
 
 	return attribute_statistics_update_internal(reloid, attname, attnum,
-												inherited, args);
+												inherited,
+												&args[ATTARG_VERSION],
+												&args[ATTARG_NULL_FRAC],
+												&args[ATTARG_AVG_WIDTH],
+												&args[ATTARG_N_DISTINCT],
+												&args[ATTARG_MOST_COMMON_VALS],
+												&args[ATTARG_MOST_COMMON_FREQS],
+												&args[ATTARG_HISTOGRAM_BOUNDS],
+												&args[ATTARG_CORRELATION],
+												&args[ATTARG_MOST_COMMON_ELEMS],
+												&args[ATTARG_MOST_COMMON_ELEM_FREQS],
+												&args[ATTARG_ELEM_COUNT_HISTOGRAM],
+												&args[ATTARG_RANGE_LENGTH_HISTOGRAM],
+												&args[ATTARG_RANGE_EMPTY_FRAC],
+												&args[ATTARG_RANGE_BOUNDS_HISTOGRAM]
+		);
 }
 
 /*
@@ -216,7 +244,21 @@ attribute_statistics_update(const NullableDatum *args)
 static bool
 attribute_statistics_update_internal(Oid reloid,
 									 const char *attname, AttrNumber attnum,
-									 bool inherited, const NullableDatum *args)
+									 bool inherited,
+									 const NullableDatum *version,
+									 const NullableDatum *null_frac,
+									 const NullableDatum *avg_width,
+									 const NullableDatum *n_distinct,
+									 const NullableDatum *most_common_vals,
+									 const NullableDatum *most_common_freqs,
+									 const NullableDatum *histogram_bounds,
+									 const NullableDatum *correlation,
+									 const NullableDatum *most_common_elems,
+									 const NullableDatum *most_common_elem_freqs,
+									 const NullableDatum *elem_count_histogram,
+									 const NullableDatum *range_length_histogram,
+									 const NullableDatum *range_empty_frac,
+									 const NullableDatum *range_bounds_histogram)
 {
 	Relation	starel;
 	HeapTuple	statup;
@@ -233,16 +275,16 @@ attribute_statistics_update_internal(Oid reloid,
 
 	FmgrInfo	array_in_fn;
 
-	bool		do_mcv = !args[ATTARG_MOST_COMMON_FREQS].isnull &&
-		!args[ATTARG_MOST_COMMON_VALS].isnull;
-	bool		do_histogram = !args[ATTARG_HISTOGRAM_BOUNDS].isnull;
-	bool		do_correlation = !args[ATTARG_CORRELATION].isnull;
-	bool		do_mcelem = !args[ATTARG_MOST_COMMON_ELEMS].isnull &&
-		!args[ATTARG_MOST_COMMON_ELEM_FREQS].isnull;
-	bool		do_dechist = !args[ATTARG_ELEM_COUNT_HISTOGRAM].isnull;
-	bool		do_bounds_histogram = !args[ATTARG_RANGE_BOUNDS_HISTOGRAM].isnull;
-	bool		do_range_length_histogram = !args[ATTARG_RANGE_LENGTH_HISTOGRAM].isnull &&
-		!args[ATTARG_RANGE_EMPTY_FRAC].isnull;
+	bool		do_mcv = !most_common_freqs->isnull &&
+		!most_common_vals->isnull;
+	bool		do_histogram = !histogram_bounds->isnull;
+	bool		do_correlation = !correlation->isnull;
+	bool		do_mcelem = !most_common_elems->isnull &&
+		!most_common_elem_freqs->isnull;
+	bool		do_dechist = !elem_count_histogram->isnull;
+	bool		do_bounds_histogram = !range_bounds_histogram->isnull;
+	bool		do_range_length_histogram = !range_length_histogram->isnull &&
+		!range_empty_frac->isnull;
 
 	Datum		values[Natts_pg_statistic] = {0};
 	bool		nulls[Natts_pg_statistic] = {0};
@@ -255,25 +297,27 @@ attribute_statistics_update_internal(Oid reloid,
 	 * and set the corresponding argument to NULL in fcinfo.
 	 */
 
-	if (!stats_check_arg_array(&args[ATTARG_MOST_COMMON_FREQS], attarginfo[ATTARG_MOST_COMMON_FREQS].argname))
+	if (!stats_check_arg_array(most_common_freqs,
+							   attarginfo[ATTARG_MOST_COMMON_FREQS].argname))
 	{
 		do_mcv = false;
 		result = false;
 	}
 
-	if (!stats_check_arg_array(&args[ATTARG_MOST_COMMON_ELEM_FREQS], attarginfo[ATTARG_MOST_COMMON_ELEM_FREQS].argname))
+	if (!stats_check_arg_array(most_common_elem_freqs,
+							   attarginfo[ATTARG_MOST_COMMON_ELEM_FREQS].argname))
 	{
 		do_mcelem = false;
 		result = false;
 	}
-	if (!stats_check_arg_array(&args[ATTARG_ELEM_COUNT_HISTOGRAM], attarginfo[ATTARG_ELEM_COUNT_HISTOGRAM].argname))
+	if (!stats_check_arg_array(elem_count_histogram,
+							   attarginfo[ATTARG_ELEM_COUNT_HISTOGRAM].argname))
 	{
 		do_dechist = false;
 		result = false;
 	}
 
-	if (!stats_check_arg_pair(&args[ATTARG_MOST_COMMON_VALS],
-							  &args[ATTARG_MOST_COMMON_FREQS],
+	if (!stats_check_arg_pair(most_common_vals, most_common_freqs,
 							  attarginfo[ATTARG_MOST_COMMON_VALS].argname,
 							  attarginfo[ATTARG_MOST_COMMON_FREQS].argname))
 	{
@@ -281,8 +325,7 @@ attribute_statistics_update_internal(Oid reloid,
 		result = false;
 	}
 
-	if (!stats_check_arg_pair(&args[ATTARG_MOST_COMMON_ELEMS],
-							  &args[ATTARG_MOST_COMMON_ELEM_FREQS],
+	if (!stats_check_arg_pair(most_common_elems, most_common_elem_freqs,
 							  attarginfo[ATTARG_MOST_COMMON_ELEMS].argname,
 							  attarginfo[ATTARG_MOST_COMMON_ELEM_FREQS].argname))
 	{
@@ -290,8 +333,7 @@ attribute_statistics_update_internal(Oid reloid,
 		result = false;
 	}
 
-	if (!stats_check_arg_pair(&args[ATTARG_RANGE_LENGTH_HISTOGRAM],
-							  &args[ATTARG_RANGE_EMPTY_FRAC],
+	if (!stats_check_arg_pair(range_length_histogram, range_empty_frac,
 							  attarginfo[ATTARG_RANGE_LENGTH_HISTOGRAM].argname,
 							  attarginfo[ATTARG_RANGE_EMPTY_FRAC].argname))
 	{
@@ -367,19 +409,19 @@ attribute_statistics_update_internal(Oid reloid,
 								 replaces);
 
 	/* if specified, set to argument values */
-	if (!args[ATTARG_NULL_FRAC].isnull)
+	if (!null_frac->isnull)
 	{
-		values[Anum_pg_statistic_stanullfrac - 1] = args[ATTARG_NULL_FRAC].value;
+		values[Anum_pg_statistic_stanullfrac - 1] = null_frac->value;
 		replaces[Anum_pg_statistic_stanullfrac - 1] = true;
 	}
-	if (!args[ATTARG_AVG_WIDTH].isnull)
+	if (!avg_width->isnull)
 	{
-		values[Anum_pg_statistic_stawidth - 1] = args[ATTARG_AVG_WIDTH].value;
+		values[Anum_pg_statistic_stawidth - 1] = avg_width->value;
 		replaces[Anum_pg_statistic_stawidth - 1] = true;
 	}
-	if (!args[ATTARG_N_DISTINCT].isnull)
+	if (!n_distinct->isnull)
 	{
-		values[Anum_pg_statistic_stadistinct - 1] = args[ATTARG_N_DISTINCT].value;
+		values[Anum_pg_statistic_stadistinct - 1] = n_distinct->value;
 		replaces[Anum_pg_statistic_stadistinct - 1] = true;
 	}
 
@@ -387,10 +429,10 @@ attribute_statistics_update_internal(Oid reloid,
 	if (do_mcv)
 	{
 		bool		converted;
-		Datum		stanumbers = args[ATTARG_MOST_COMMON_FREQS].value;
+		Datum		stanumbers = most_common_freqs->value;
 		Datum		stavalues = statatt_build_stavalues("most_common_vals",
 														&array_in_fn,
-														args[ATTARG_MOST_COMMON_VALS].value,
+														most_common_vals->value,
 														atttypid, atttypmod,
 														&converted);
 
@@ -430,7 +472,7 @@ attribute_statistics_update_internal(Oid reloid,
 
 		stavalues = statatt_build_stavalues("histogram_bounds",
 											&array_in_fn,
-											args[ATTARG_HISTOGRAM_BOUNDS].value,
+											histogram_bounds->value,
 											atttypid, atttypmod,
 											&converted);
 
@@ -448,7 +490,7 @@ attribute_statistics_update_internal(Oid reloid,
 	/* STATISTIC_KIND_CORRELATION */
 	if (do_correlation)
 	{
-		Datum		elems[] = {args[ATTARG_CORRELATION].value};
+		Datum		elems[] = {correlation->value};
 		ArrayType  *arry = construct_array_builtin(elems, 1, FLOAT4OID);
 		Datum		stanumbers = PointerGetDatum(arry);
 
@@ -461,13 +503,13 @@ attribute_statistics_update_internal(Oid reloid,
 	/* STATISTIC_KIND_MCELEM */
 	if (do_mcelem)
 	{
-		Datum		stanumbers = args[ATTARG_MOST_COMMON_ELEM_FREQS].value;
+		Datum		stanumbers = most_common_elem_freqs->value;
 		bool		converted = false;
 		Datum		stavalues;
 
 		stavalues = statatt_build_stavalues("most_common_elems",
 											&array_in_fn,
-											args[ATTARG_MOST_COMMON_ELEMS].value,
+											most_common_elems->value,
 											elemtypid, atttypmod,
 											&converted);
 
@@ -485,7 +527,7 @@ attribute_statistics_update_internal(Oid reloid,
 	/* STATISTIC_KIND_DECHIST */
 	if (do_dechist)
 	{
-		Datum		stanumbers = args[ATTARG_ELEM_COUNT_HISTOGRAM].value;
+		Datum		stanumbers = elem_count_histogram->value;
 
 		statatt_set_slot(values, nulls, replaces,
 						 STATISTIC_KIND_DECHIST,
@@ -507,7 +549,7 @@ attribute_statistics_update_internal(Oid reloid,
 
 		stavalues = statatt_build_stavalues("range_bounds_histogram",
 											&array_in_fn,
-											args[ATTARG_RANGE_BOUNDS_HISTOGRAM].value,
+											range_bounds_histogram->value,
 											atttypid, atttypmod,
 											&converted);
 
@@ -527,7 +569,7 @@ attribute_statistics_update_internal(Oid reloid,
 	if (do_range_length_histogram)
 	{
 		/* The anyarray is always a float8[] for this stakind */
-		Datum		elems[] = {args[ATTARG_RANGE_EMPTY_FRAC].value};
+		Datum		elems[] = {range_empty_frac->value};
 		ArrayType  *arry = construct_array_builtin(elems, 1, FLOAT4OID);
 		Datum		stanumbers = PointerGetDatum(arry);
 
@@ -536,7 +578,7 @@ attribute_statistics_update_internal(Oid reloid,
 
 		stavalues = statatt_build_stavalues("range_length_histogram",
 											&array_in_fn,
-											args[ATTARG_RANGE_LENGTH_HISTOGRAM].value,
+											range_length_histogram->value,
 											FLOAT8OID, 0, &converted);
 
 		if (converted)
@@ -734,7 +776,8 @@ import_attribute_statistics(Relation rel, AttrNumber attnum, bool inherited,
 							const NullableDatum *range_empty_frac,
 							const NullableDatum *range_bounds_histogram)
 {
-	LOCAL_FCINFO(newfcinfo, ATTARG_NUM_ATTARGS);
+	NullableDatum null_datum = {.value = (Datum) 0, .isnull = true};
+
 	Oid			reloid = RelationGetRelid(rel);
 	char	   *relname = RelationGetRelationName(rel);
 	char	   *attname = get_attname(reloid, attnum, true);
@@ -753,6 +796,9 @@ import_attribute_statistics(Relation rel, AttrNumber attnum, bool inherited,
 	Assert(range_empty_frac);
 	Assert(range_bounds_histogram);
 
+	if (!version)
+		version = &null_datum;
+
 	/* annoyingly, get_attname doesn't check attisdropped */
 	if (attname == NULL ||
 		!SearchSysCacheExistsAttName(reloid, attname))
@@ -761,39 +807,18 @@ import_attribute_statistics(Relation rel, AttrNumber attnum, bool inherited,
 				 errmsg("column %d of relation \"%s\" does not exist",
 						attnum, relname)));
 
-	InitFunctionCallInfoData(*newfcinfo, NULL, ATTARG_NUM_ATTARGS,
-							 InvalidOid, NULL, NULL);
-
-	newfcinfo->args[ATTARG_ATTRELSCHEMA].value =
-		CStringGetTextDatum(get_namespace_name(RelationGetNamespace(rel)));
-	newfcinfo->args[ATTARG_ATTRELSCHEMA].isnull = false;
-	newfcinfo->args[ATTARG_ATTRELNAME].value = CStringGetTextDatum(relname);
-	newfcinfo->args[ATTARG_ATTRELNAME].isnull = false;
-	newfcinfo->args[ATTARG_ATTNAME].value = CStringGetTextDatum(attname);
-	newfcinfo->args[ATTARG_ATTNAME].isnull = false;
-	newfcinfo->args[ATTARG_ATTNUM].value = Int16GetDatum(attnum);
-	newfcinfo->args[ATTARG_ATTNUM].isnull = false;
-	newfcinfo->args[ATTARG_INHERITED].value = BoolGetDatum(inherited);
-	newfcinfo->args[ATTARG_INHERITED].isnull = false;
-
-	newfcinfo->args[ATTARG_VERSION].value = (version) ? version->value : (Datum) 0;
-	newfcinfo->args[ATTARG_VERSION].isnull = (version) ? version->isnull : true;
-	newfcinfo->args[ATTARG_NULL_FRAC] = *null_frac;
-	newfcinfo->args[ATTARG_AVG_WIDTH] = *avg_width;
-	newfcinfo->args[ATTARG_N_DISTINCT] = *n_distinct;
-	newfcinfo->args[ATTARG_MOST_COMMON_VALS] = *most_common_vals;
-	newfcinfo->args[ATTARG_MOST_COMMON_FREQS] = *most_common_freqs;
-	newfcinfo->args[ATTARG_HISTOGRAM_BOUNDS] = *histogram_bounds;
-	newfcinfo->args[ATTARG_CORRELATION] = *correlation;
-	newfcinfo->args[ATTARG_MOST_COMMON_ELEMS] = *most_common_elems;
-	newfcinfo->args[ATTARG_MOST_COMMON_ELEM_FREQS] = *most_common_elem_freqs;
-	newfcinfo->args[ATTARG_ELEM_COUNT_HISTOGRAM] = *elem_count_histogram;
-	newfcinfo->args[ATTARG_RANGE_LENGTH_HISTOGRAM] = *range_length_histogram;
-	newfcinfo->args[ATTARG_RANGE_EMPTY_FRAC] = *range_empty_frac;
-	newfcinfo->args[ATTARG_RANGE_BOUNDS_HISTOGRAM] = *range_bounds_histogram;
-
 	return attribute_statistics_update_internal(reloid, attname, attnum,
-												inherited, newfcinfo->args);
+												inherited, version,
+												null_frac, avg_width,
+												n_distinct, most_common_vals,
+												most_common_freqs,
+												histogram_bounds, correlation,
+												most_common_elems,
+												most_common_elem_freqs,
+												elem_count_histogram,
+												range_length_histogram,
+												range_empty_frac,
+												range_bounds_histogram);
 }
 
 /*
diff --git a/src/backend/statistics/extended_stats_funcs.c b/src/backend/statistics/extended_stats_funcs.c
index 0c84160a824..58692bcf1f0 100644
--- a/src/backend/statistics/extended_stats_funcs.c
+++ b/src/backend/statistics/extended_stats_funcs.c
@@ -311,6 +311,11 @@ upsert_pg_statistic_ext_data(const Datum *values, const bool *nulls,
  * like when the statistics object or its schema do not exist, a conversion
  * failure on one statistic kind, or when other statistic kinds may still
  * be updated.
+ *
+ * Unlike its attribute and relation equivalent functions, there is no
+ * corresponding extended_statistics_update_internal() function.  This is mostly
+ * because there is not yet an internal update use-case where the statitics
+ * object is already locked.
  */
 static bool
 extended_statistics_update(const NullableDatum *args)
diff --git a/src/backend/statistics/relation_stats.c b/src/backend/statistics/relation_stats.c
index 2e62cf5b9e3..99432502245 100644
--- a/src/backend/statistics/relation_stats.c
+++ b/src/backend/statistics/relation_stats.c
@@ -63,7 +63,11 @@ static struct StatsArgInfo relarginfo[] =
 
 static bool relation_statistics_update(const NullableDatum *args);
 static bool relation_statistics_update_internal(Oid reloid,
-												const NullableDatum *args);
+												const NullableDatum *version,
+												const NullableDatum *relpages,
+												const NullableDatum *reltuples,
+												const NullableDatum *relallvisible,
+												const NullableDatum *relallfrozen);
 
 /*
  * Internal function for modifying statistics for a relation.
@@ -92,22 +96,32 @@ relation_statistics_update(const NullableDatum *args)
 									  ShareUpdateExclusiveLock, 0,
 									  RangeVarCallbackForStats, &locked_table);
 
-	return relation_statistics_update_internal(reloid, args);
+	return relation_statistics_update_internal(reloid,
+											   &args[RELARG_VERSION],
+											   &args[RELARG_RELPAGES],
+											   &args[RELARG_RELTUPLES],
+											   &args[RELARG_RELALLVISIBLE],
+											   &args[RELARG_RELALLFROZEN]);
 }
 
 /*
  * Workhorse function for relation_statistics_update.
  */
 static bool
-relation_statistics_update_internal(Oid reloid, const NullableDatum *args)
+relation_statistics_update_internal(Oid reloid,
+									const NullableDatum *version,
+									const NullableDatum *relpages,
+									const NullableDatum *reltuples,
+									const NullableDatum *relallvisible,
+									const NullableDatum *relallfrozen)
 {
-	BlockNumber relpages = 0;
+	BlockNumber num_relpages = 0;
 	bool		update_relpages = false;
-	float		reltuples = 0;
+	float		num_reltuples = 0;
 	bool		update_reltuples = false;
-	BlockNumber relallvisible = 0;
+	BlockNumber num_relallvisible = 0;
 	bool		update_relallvisible = false;
-	BlockNumber relallfrozen = 0;
+	BlockNumber num_relallfrozen = 0;
 	bool		update_relallfrozen = false;
 	Relation	crel;
 	HeapTuple	ctup;
@@ -118,23 +132,29 @@ relation_statistics_update_internal(Oid reloid, const NullableDatum *args)
 	int			nreplaces = 0;
 	bool		result = true;
 
-	if (!args[RELARG_RELPAGES].isnull)
+	Assert(version);
+	Assert(relpages);
+	Assert(reltuples);
+	Assert(relallvisible);
+	Assert(relallfrozen);
+
+	if (!relpages->isnull)
 	{
-		relpages = DatumGetUInt32(args[RELARG_RELPAGES].value);
+		num_relpages = DatumGetUInt32(relpages->value);
 		update_relpages = true;
 	}
 
-	if (!args[RELARG_RELTUPLES].isnull)
+	if (!reltuples->isnull)
 	{
-		reltuples = DatumGetFloat4(args[RELARG_RELTUPLES].value);
-		if (isnan(reltuples) || isinf(reltuples))
+		num_reltuples = DatumGetFloat4(reltuples->value);
+		if (isnan(num_reltuples) || isinf(num_reltuples))
 		{
 			ereport(WARNING,
 					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 					 errmsg("argument \"%s\" must be a finite value", "reltuples")));
 			result = false;
 		}
-		else if (reltuples < -1.0)
+		else if (num_reltuples < -1.0)
 		{
 			ereport(WARNING,
 					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
@@ -145,15 +165,15 @@ relation_statistics_update_internal(Oid reloid, const NullableDatum *args)
 			update_reltuples = true;
 	}
 
-	if (!args[RELARG_RELALLVISIBLE].isnull)
+	if (!relallvisible->isnull)
 	{
-		relallvisible = DatumGetUInt32(args[RELARG_RELALLVISIBLE].value);
+		num_relallvisible = DatumGetUInt32(relallvisible->value);
 		update_relallvisible = true;
 	}
 
-	if (!args[RELARG_RELALLFROZEN].isnull)
+	if (!relallfrozen->isnull)
 	{
-		relallfrozen = DatumGetUInt32(args[RELARG_RELALLFROZEN].value);
+		num_relallfrozen = DatumGetUInt32(relallfrozen->value);
 		update_relallfrozen = true;
 	}
 
@@ -169,31 +189,31 @@ relation_statistics_update_internal(Oid reloid, const NullableDatum *args)
 
 	pgcform = (Form_pg_class) GETSTRUCT(ctup);
 
-	if (update_relpages && relpages != pgcform->relpages)
+	if (update_relpages && num_relpages != pgcform->relpages)
 	{
 		replaces[nreplaces] = Anum_pg_class_relpages;
-		values[nreplaces] = UInt32GetDatum(relpages);
+		values[nreplaces] = relpages->value;
 		nreplaces++;
 	}
 
-	if (update_reltuples && reltuples != pgcform->reltuples)
+	if (update_reltuples && num_reltuples != pgcform->reltuples)
 	{
 		replaces[nreplaces] = Anum_pg_class_reltuples;
-		values[nreplaces] = Float4GetDatum(reltuples);
+		values[nreplaces] = reltuples->value;
 		nreplaces++;
 	}
 
-	if (update_relallvisible && relallvisible != pgcform->relallvisible)
+	if (update_relallvisible && num_relallvisible != pgcform->relallvisible)
 	{
 		replaces[nreplaces] = Anum_pg_class_relallvisible;
-		values[nreplaces] = UInt32GetDatum(relallvisible);
+		values[nreplaces] = relallvisible->value;
 		nreplaces++;
 	}
 
-	if (update_relallfrozen && relallfrozen != pgcform->relallfrozen)
+	if (update_relallfrozen && num_relallfrozen != pgcform->relallfrozen)
 	{
 		replaces[nreplaces] = Anum_pg_class_relallfrozen;
-		values[nreplaces] = UInt32GetDatum(relallfrozen);
+		values[nreplaces] = relallfrozen->value;
 		nreplaces++;
 	}
 
@@ -225,26 +245,24 @@ relation_statistics_update_internal(Oid reloid, const NullableDatum *args)
 Datum
 pg_clear_relation_stats(PG_FUNCTION_ARGS)
 {
-	LOCAL_FCINFO(newfcinfo, RELARG_NUM_RELARGS);
-
-	InitFunctionCallInfoData(*newfcinfo, NULL, 6, InvalidOid, NULL, NULL);
-
-	newfcinfo->args[RELARG_SCHEMA].value = PG_GETARG_DATUM(RELARG_SCHEMA);
-	newfcinfo->args[RELARG_SCHEMA].isnull = PG_ARGISNULL(RELARG_SCHEMA);
-	newfcinfo->args[RELARG_RELNAME].value = PG_GETARG_DATUM(RELARG_RELNAME);
-	newfcinfo->args[RELARG_RELNAME].isnull = PG_ARGISNULL(RELARG_RELNAME);
-	newfcinfo->args[RELARG_VERSION].value = (Datum) 0;
-	newfcinfo->args[RELARG_VERSION].isnull = true;
-	newfcinfo->args[RELARG_RELPAGES].value = UInt32GetDatum(0);
-	newfcinfo->args[RELARG_RELPAGES].isnull = false;
-	newfcinfo->args[RELARG_RELTUPLES].value = Float4GetDatum(-1.0);
-	newfcinfo->args[RELARG_RELTUPLES].isnull = false;
-	newfcinfo->args[RELARG_RELALLVISIBLE].value = UInt32GetDatum(0);
-	newfcinfo->args[RELARG_RELALLVISIBLE].isnull = false;
-	newfcinfo->args[RELARG_RELALLFROZEN].value = UInt32GetDatum(0);
-	newfcinfo->args[RELARG_RELALLFROZEN].isnull = false;
-
-	relation_statistics_update(newfcinfo->args);
+	NullableDatum args[RELARG_NUM_RELARGS];
+
+	args[RELARG_SCHEMA].value = PG_GETARG_DATUM(RELARG_SCHEMA);
+	args[RELARG_SCHEMA].isnull = PG_ARGISNULL(RELARG_SCHEMA);
+	args[RELARG_RELNAME].value = PG_GETARG_DATUM(RELARG_RELNAME);
+	args[RELARG_RELNAME].isnull = PG_ARGISNULL(RELARG_RELNAME);
+	args[RELARG_VERSION].value = (Datum) 0;
+	args[RELARG_VERSION].isnull = true;
+	args[RELARG_RELPAGES].value = UInt32GetDatum(0);
+	args[RELARG_RELPAGES].isnull = false;
+	args[RELARG_RELTUPLES].value = Float4GetDatum(-1.0);
+	args[RELARG_RELTUPLES].isnull = false;
+	args[RELARG_RELALLVISIBLE].value = UInt32GetDatum(0);
+	args[RELARG_RELALLVISIBLE].isnull = false;
+	args[RELARG_RELALLFROZEN].value = UInt32GetDatum(0);
+	args[RELARG_RELALLFROZEN].isnull = false;
+
+	relation_statistics_update(args);
 	PG_RETURN_VOID();
 }
 
@@ -279,30 +297,18 @@ import_relation_statistics(Relation rel,
 						   const NullableDatum *relallvisible,
 						   const NullableDatum *relallfrozen)
 {
-	LOCAL_FCINFO(newfcinfo, RELARG_NUM_RELARGS);
+	NullableDatum null_datum = {.value = (Datum) 0, .isnull = true};
 
 	Assert(relpages);
 	Assert(reltuples);
 	Assert(relallvisible);
 	Assert(relallfrozen);
 
-	InitFunctionCallInfoData(*newfcinfo, NULL, RELARG_NUM_RELARGS,
-							 InvalidOid, NULL, NULL);
-
-	newfcinfo->args[RELARG_SCHEMA].value =
-		CStringGetTextDatum(get_namespace_name(RelationGetNamespace(rel)));
-	newfcinfo->args[RELARG_SCHEMA].isnull = false;
-	newfcinfo->args[RELARG_RELNAME].value =
-		CStringGetTextDatum(RelationGetRelationName(rel));
-	newfcinfo->args[RELARG_RELNAME].isnull = false;
-	newfcinfo->args[RELARG_VERSION].value = (version) ? version->value : (Datum) 0;
-	newfcinfo->args[RELARG_VERSION].isnull = (version) ? version->isnull : true;
-
-	newfcinfo->args[RELARG_RELPAGES] = *relpages;
-	newfcinfo->args[RELARG_RELTUPLES] = *reltuples;
-	newfcinfo->args[RELARG_RELALLVISIBLE] = *relallvisible;
-	newfcinfo->args[RELARG_RELALLFROZEN] = *relallfrozen;
-
-	return relation_statistics_update_internal(RelationGetRelid(rel),
-											   newfcinfo->args);
+	/* Handle optional parameters */
+	if (!version)
+		version = &null_datum;
+
+	return relation_statistics_update_internal(RelationGetRelid(rel), version,
+											   relpages, reltuples,
+											   relallvisible, relallfrozen);
 }
-- 
2.50.1 (Apple Git-155)

