From d9f9841cb66691d0c1a8ad2e407253cb63c654b3 Mon Sep 17 00:00:00 2001
From: Corey Huinker <corey.huinker@gmail.com>
Date: Sun, 28 Jun 2026 17:21:51 -0500
Subject: [PATCH v3 08/15] Change stats_fill_fcinfo_from_arg_pairs to
 NullableDatum array.

Change stats_fill_fcinfo_from_arg_pairs to NullableDatum array, and in
doing so rename to stats_fill_args_from_arg_pairs. Change all callers to
instead initialize an NullableDatum array of the proper size instead of
a full FunctionCallInfoData structure.
---
 src/backend/statistics/attribute_stats.c      | 39 +++++++++----------
 src/backend/statistics/extended_stats_funcs.c |  9 ++---
 src/backend/statistics/relation_stats.c       | 28 ++++++-------
 src/backend/statistics/stat_utils.c           | 24 ++++++------
 src/include/statistics/stat_utils.h           |  6 +--
 5 files changed, 48 insertions(+), 58 deletions(-)

diff --git a/src/backend/statistics/attribute_stats.c b/src/backend/statistics/attribute_stats.c
index 455bce7b2cf..f19a0d1e373 100644
--- a/src/backend/statistics/attribute_stats.c
+++ b/src/backend/statistics/attribute_stats.c
@@ -104,7 +104,7 @@ static struct StatsArgInfo cleararginfo[] =
 	[C_ATTARG_NUM_ATTARGS] = {0}
 };
 
-static bool attribute_statistics_update(FunctionCallInfo fcinfo);
+static bool attribute_statistics_update(const NullableDatum *args);
 static bool attribute_statistics_update_internal(Oid reloid,
 												 const char *attname,
 												 AttrNumber attnum,
@@ -131,7 +131,7 @@ static bool delete_pg_statistic(Oid reloid, AttrNumber attnum, bool stainherit);
  * and other statistic kinds may still be updated.
  */
 static bool
-attribute_statistics_update(FunctionCallInfo fcinfo)
+attribute_statistics_update(const NullableDatum *args)
 {
 	char	   *nspname;
 	char	   *relname;
@@ -141,11 +141,11 @@ attribute_statistics_update(FunctionCallInfo fcinfo)
 	bool		inherited;
 	Oid			locked_table = InvalidOid;
 
-	stats_check_required_arg(fcinfo->args, attarginfo, ATTARG_ATTRELSCHEMA);
-	stats_check_required_arg(fcinfo->args, attarginfo, ATTARG_ATTRELNAME);
+	stats_check_required_arg(args, attarginfo, ATTARG_ATTRELSCHEMA);
+	stats_check_required_arg(args, attarginfo, ATTARG_ATTRELNAME);
 
-	nspname = TextDatumGetCString(PG_GETARG_DATUM(ATTARG_ATTRELSCHEMA));
-	relname = TextDatumGetCString(PG_GETARG_DATUM(ATTARG_ATTRELNAME));
+	nspname = TextDatumGetCString(args[ATTARG_ATTRELSCHEMA].value);
+	relname = TextDatumGetCString(args[ATTARG_ATTRELNAME].value);
 
 	if (RecoveryInProgress())
 		ereport(ERROR,
@@ -159,13 +159,13 @@ attribute_statistics_update(FunctionCallInfo fcinfo)
 									  RangeVarCallbackForStats, &locked_table);
 
 	/* user can specify either attname or attnum, but not both */
-	if (!PG_ARGISNULL(ATTARG_ATTNAME))
+	if (!args[ATTARG_ATTNAME].isnull)
 	{
-		if (!PG_ARGISNULL(ATTARG_ATTNUM))
+		if (!args[ATTARG_ATTNUM].isnull)
 			ereport(ERROR,
 					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 					 errmsg("cannot specify both \"%s\" and \"%s\"", "attname", "attnum")));
-		attname = TextDatumGetCString(PG_GETARG_DATUM(ATTARG_ATTNAME));
+		attname = TextDatumGetCString(args[ATTARG_ATTNAME].value);
 		attnum = get_attnum(reloid, attname);
 		/* note that this test covers attisdropped cases too: */
 		if (attnum == InvalidAttrNumber)
@@ -174,9 +174,9 @@ attribute_statistics_update(FunctionCallInfo fcinfo)
 					 errmsg("column \"%s\" of relation \"%s\" does not exist",
 							attname, relname)));
 	}
-	else if (!PG_ARGISNULL(ATTARG_ATTNUM))
+	else if (!args[ATTARG_ATTNUM].isnull)
 	{
-		attnum = PG_GETARG_INT16(ATTARG_ATTNUM);
+		attnum = DatumGetInt16(args[ATTARG_ATTNUM].value);
 		attname = get_attname(reloid, attnum, true);
 		/* annoyingly, get_attname doesn't check attisdropped */
 		if (attname == NULL ||
@@ -201,11 +201,11 @@ attribute_statistics_update(FunctionCallInfo fcinfo)
 				 errmsg("cannot modify statistics on system column \"%s\"",
 						attname)));
 
-	stats_check_required_arg(fcinfo->args, attarginfo, ATTARG_INHERITED);
-	inherited = PG_GETARG_BOOL(ATTARG_INHERITED);
+	stats_check_required_arg(args, attarginfo, ATTARG_INHERITED);
+	inherited = DatumGetBool(args[ATTARG_INHERITED].value);
 
 	return attribute_statistics_update_internal(reloid, attname, attnum,
-												inherited, fcinfo->args);
+												inherited, args);
 }
 
 /*
@@ -691,17 +691,14 @@ pg_clear_attribute_stats(PG_FUNCTION_ARGS)
 Datum
 pg_restore_attribute_stats(PG_FUNCTION_ARGS)
 {
-	LOCAL_FCINFO(positional_fcinfo, ATTARG_NUM_ATTARGS);
+	NullableDatum positional_args[ATTARG_NUM_ATTARGS];
 	bool		result = true;
 
-	InitFunctionCallInfoData(*positional_fcinfo, NULL, ATTARG_NUM_ATTARGS,
-							 InvalidOid, NULL, NULL);
-
-	if (!stats_fill_fcinfo_from_arg_pairs(fcinfo, positional_fcinfo,
-										  attarginfo))
+	if (!stats_fill_args_from_arg_pairs(fcinfo, positional_args,
+										attarginfo))
 		result = false;
 
-	if (!attribute_statistics_update(positional_fcinfo))
+	if (!attribute_statistics_update(positional_args))
 		result = false;
 
 	PG_RETURN_BOOL(result);
diff --git a/src/backend/statistics/extended_stats_funcs.c b/src/backend/statistics/extended_stats_funcs.c
index 1a29dc97e34..be31ac67fba 100644
--- a/src/backend/statistics/extended_stats_funcs.c
+++ b/src/backend/statistics/extended_stats_funcs.c
@@ -1724,16 +1724,13 @@ delete_pg_statistic_ext_data(Oid stxoid, bool inherited)
 Datum
 pg_restore_extended_stats(PG_FUNCTION_ARGS)
 {
-	LOCAL_FCINFO(positional_fcinfo, EXTARG_NUM_EXTARGS);
+	NullableDatum positional_args[EXTARG_NUM_EXTARGS];
 	bool		result = true;
 
-	InitFunctionCallInfoData(*positional_fcinfo, NULL, EXTARG_NUM_EXTARGS,
-							 InvalidOid, NULL, NULL);
-
-	if (!stats_fill_fcinfo_from_arg_pairs(fcinfo, positional_fcinfo, extarginfo))
+	if (!stats_fill_args_from_arg_pairs(fcinfo, positional_args, extarginfo))
 		result = false;
 
-	if (!extended_statistics_update(positional_fcinfo->args))
+	if (!extended_statistics_update(positional_args))
 		result = false;
 
 	PG_RETURN_BOOL(result);
diff --git a/src/backend/statistics/relation_stats.c b/src/backend/statistics/relation_stats.c
index 54e8609cba6..03312985bc3 100644
--- a/src/backend/statistics/relation_stats.c
+++ b/src/backend/statistics/relation_stats.c
@@ -59,7 +59,7 @@ static struct StatsArgInfo relarginfo[] =
 	[RELARG_NUM_RELARGS] = {0}
 };
 
-static bool relation_statistics_update(FunctionCallInfo fcinfo);
+static bool relation_statistics_update(const NullableDatum *args);
 static bool relation_statistics_update_internal(Oid reloid,
 												const NullableDatum *args);
 
@@ -67,18 +67,18 @@ static bool relation_statistics_update_internal(Oid reloid,
  * Internal function for modifying statistics for a relation.
  */
 static bool
-relation_statistics_update(FunctionCallInfo fcinfo)
+relation_statistics_update(const NullableDatum *args)
 {
 	char	   *nspname;
 	char	   *relname;
 	Oid			reloid;
 	Oid			locked_table = InvalidOid;
 
-	stats_check_required_arg(fcinfo->args, relarginfo, RELARG_SCHEMA);
-	stats_check_required_arg(fcinfo->args, relarginfo, RELARG_RELNAME);
+	stats_check_required_arg(args, relarginfo, RELARG_SCHEMA);
+	stats_check_required_arg(args, relarginfo, RELARG_RELNAME);
 
-	nspname = TextDatumGetCString(PG_GETARG_DATUM(RELARG_SCHEMA));
-	relname = TextDatumGetCString(PG_GETARG_DATUM(RELARG_RELNAME));
+	nspname = TextDatumGetCString(args[RELARG_SCHEMA].value);
+	relname = TextDatumGetCString(args[RELARG_RELNAME].value);
 
 	if (RecoveryInProgress())
 		ereport(ERROR,
@@ -90,7 +90,7 @@ relation_statistics_update(FunctionCallInfo fcinfo)
 									  ShareUpdateExclusiveLock, 0,
 									  RangeVarCallbackForStats, &locked_table);
 
-	return relation_statistics_update_internal(reloid, fcinfo->args);
+	return relation_statistics_update_internal(reloid, args);
 }
 
 /*
@@ -240,25 +240,21 @@ pg_clear_relation_stats(PG_FUNCTION_ARGS)
 	newfcinfo->args[5].value = UInt32GetDatum(0);
 	newfcinfo->args[5].isnull = false;
 
-	relation_statistics_update(newfcinfo);
+	relation_statistics_update(newfcinfo->args);
 	PG_RETURN_VOID();
 }
 
 Datum
 pg_restore_relation_stats(PG_FUNCTION_ARGS)
 {
-	LOCAL_FCINFO(positional_fcinfo, RELARG_NUM_RELARGS);
+	NullableDatum positional_args[RELARG_NUM_RELARGS];
 	bool		result = true;
 
-	InitFunctionCallInfoData(*positional_fcinfo, NULL,
-							 RELARG_NUM_RELARGS,
-							 InvalidOid, NULL, NULL);
-
-	if (!stats_fill_fcinfo_from_arg_pairs(fcinfo, positional_fcinfo,
-										  relarginfo))
+	if (!stats_fill_args_from_arg_pairs(fcinfo, positional_args,
+										relarginfo))
 		result = false;
 
-	if (!relation_statistics_update(positional_fcinfo))
+	if (!relation_statistics_update(positional_args))
 		result = false;
 
 	PG_RETURN_BOOL(result);
diff --git a/src/backend/statistics/stat_utils.c b/src/backend/statistics/stat_utils.c
index f248db97959..df3bf3d6914 100644
--- a/src/backend/statistics/stat_utils.c
+++ b/src/backend/statistics/stat_utils.c
@@ -340,17 +340,17 @@ statatt_get_index_expr(Relation rel, int attnum)
 
 /*
  * Translate variadic argument pairs from 'pairs_fcinfo' into a
- * 'positional_fcinfo' appropriate for calling relation_statistics_update() or
- * attribute_statistics_update() with positional arguments.
+ * NullableDatum[] appropriate for calling the internal statistics update
+ * functions for relation stats, attribute stats, or extended stats.
  *
- * Caller should have already initialized positional_fcinfo with a size
- * appropriate for calling the intended positional function, and arginfo
- * should also match the intended positional function.
+ * Caller should have already initialized args with a size appropriate for
+ * calling the intended function, and arginfo should also match the intended
+ * function.
  */
 bool
-stats_fill_fcinfo_from_arg_pairs(FunctionCallInfo pairs_fcinfo,
-								 FunctionCallInfo positional_fcinfo,
-								 struct StatsArgInfo *arginfo)
+stats_fill_args_from_arg_pairs(FunctionCallInfo pairs_fcinfo,
+							   NullableDatum *positional_args,
+							   struct StatsArgInfo *arginfo)
 {
 	Datum	   *args;
 	bool	   *argnulls;
@@ -361,8 +361,8 @@ stats_fill_fcinfo_from_arg_pairs(FunctionCallInfo pairs_fcinfo,
 	/* clear positional args */
 	for (int i = 0; arginfo[i].argname != NULL; i++)
 	{
-		positional_fcinfo->args[i].value = (Datum) 0;
-		positional_fcinfo->args[i].isnull = true;
+		positional_args[i].value = (Datum) 0;
+		positional_args[i].isnull = true;
 	}
 
 	nargs = extract_variadic_args(pairs_fcinfo, 0, true,
@@ -417,8 +417,8 @@ stats_fill_fcinfo_from_arg_pairs(FunctionCallInfo pairs_fcinfo,
 			continue;
 		}
 
-		positional_fcinfo->args[argnum].value = args[i + 1];
-		positional_fcinfo->args[argnum].isnull = false;
+		positional_args[argnum].value = args[i + 1];
+		positional_args[argnum].isnull = false;
 	}
 
 	return result;
diff --git a/src/include/statistics/stat_utils.h b/src/include/statistics/stat_utils.h
index db7b770bd32..39027a4ab03 100644
--- a/src/include/statistics/stat_utils.h
+++ b/src/include/statistics/stat_utils.h
@@ -38,9 +38,9 @@ extern bool stats_check_arg_pair(const NullableDatum *args,
 extern void RangeVarCallbackForStats(const RangeVar *relation,
 									 Oid relId, Oid oldRelId, void *arg);
 
-extern bool stats_fill_fcinfo_from_arg_pairs(FunctionCallInfo pairs_fcinfo,
-											 FunctionCallInfo positional_fcinfo,
-											 struct StatsArgInfo *arginfo);
+extern bool stats_fill_args_from_arg_pairs(FunctionCallInfo pairs_fcinfo,
+										   NullableDatum *positional_args,
+										   struct StatsArgInfo *arginfo);
 
 extern void statatt_get_type(Oid reloid, AttrNumber attnum,
 							 Oid *atttypid, int32 *atttypmod,
-- 
2.50.1 (Apple Git-155)

