From c949ee76a7c561015534a720e9d97d3bd7cc17ba Mon Sep 17 00:00:00 2001
From: Corey Huinker <corey.huinker@gmail.com>
Date: Mon, 3 Aug 2026 15:59:40 -0400
Subject: [PATCH v3 14/15] Refactor attribute_stats update functions.

Move all functionality from attribute_statistics_update() to
pg_restore_attribute_stats() and then rename
attribute_statistics_update_internal() to attribute_statistics_update().
---
 src/backend/statistics/attribute_stats.c | 267 +++++++++++------------
 1 file changed, 126 insertions(+), 141 deletions(-)

diff --git a/src/backend/statistics/attribute_stats.c b/src/backend/statistics/attribute_stats.c
index 348ccc355df..a6710d6ef50 100644
--- a/src/backend/statistics/attribute_stats.c
+++ b/src/backend/statistics/attribute_stats.c
@@ -32,7 +32,7 @@
 
 /*
  * Positional argument numbers, names, and types for
- * attribute_statistics_update() and pg_restore_attribute_stats().
+ * pg_restore_attribute_stats().
  */
 
 enum attribute_stats_argnum
@@ -106,25 +106,24 @@ static struct StatsArgInfo cleararginfo[] =
 	[C_ATTARG_NUM_ATTARGS] = {0}
 };
 
-static bool attribute_statistics_update(const NullableDatum *args);
-static bool attribute_statistics_update_internal(Oid reloid,
-												 const char *attname,
-												 AttrNumber attnum,
-												 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);
+static bool attribute_statistics_update(Oid reloid,
+										const char *attname,
+										AttrNumber attnum,
+										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);
 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);
@@ -146,112 +145,23 @@ static bool delete_pg_statistic(Oid reloid, AttrNumber attnum, bool stainherit);
  * and other statistic kinds may still be updated.
  */
 static bool
-attribute_statistics_update(const NullableDatum *args)
-{
-	char	   *nspname;
-	char	   *relname;
-	Oid			reloid;
-	char	   *attname;
-	AttrNumber	attnum;
-	bool		inherited;
-
-	stats_check_required_arg(&args[ATTARG_ATTRELSCHEMA], attarginfo[ATTARG_ATTRELSCHEMA].argname);
-	stats_check_required_arg(&args[ATTARG_ATTRELNAME], attarginfo[ATTARG_ATTRELNAME].argname);
-
-	nspname = TextDatumGetCString(args[ATTARG_ATTRELSCHEMA].value);
-	relname = TextDatumGetCString(args[ATTARG_ATTRELNAME].value);
-
-	stats_check_recovery(ERROR);
-
-	/* lock before looking up attribute */
-	reloid = stats_check_lock_relation(nspname, relname);
-
-	/* user can specify either attname or attnum, but not both */
-	if (!args[ATTARG_ATTNAME].isnull)
-	{
-		if (!args[ATTARG_ATTNUM].isnull)
-			ereport(ERROR,
-					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-					 errmsg("cannot specify both \"%s\" and \"%s\"", "attname", "attnum")));
-		attname = TextDatumGetCString(args[ATTARG_ATTNAME].value);
-		attnum = get_attnum(reloid, attname);
-		/* note that this test covers attisdropped cases too: */
-		if (attnum == InvalidAttrNumber)
-			ereport(ERROR,
-					(errcode(ERRCODE_UNDEFINED_COLUMN),
-					 errmsg("column \"%s\" of relation \"%s\" does not exist",
-							attname, relname)));
-	}
-	else if (!args[ATTARG_ATTNUM].isnull)
-	{
-		attnum = DatumGetInt16(args[ATTARG_ATTNUM].value);
-		attname = get_attname(reloid, attnum, true);
-		/* annoyingly, get_attname doesn't check attisdropped */
-		if (attname == NULL ||
-			!SearchSysCacheExistsAttName(reloid, attname))
-			ereport(ERROR,
-					(errcode(ERRCODE_UNDEFINED_COLUMN),
-					 errmsg("column %d of relation \"%s\" does not exist",
-							attnum, relname)));
-	}
-	else
-	{
-		ereport(ERROR,
-				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-				 errmsg("must specify either \"%s\" or \"%s\"", "attname", "attnum")));
-		attname = NULL;			/* keep compiler quiet */
-		attnum = 0;
-	}
-
-	if (attnum < 0)
-		ereport(ERROR,
-				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-				 errmsg("cannot modify statistics on system column \"%s\"",
-						attname)));
-
-	stats_check_required_arg(&args[ATTARG_INHERITED], attarginfo[ATTARG_INHERITED].argname);
-	inherited = DatumGetBool(args[ATTARG_INHERITED].value);
-
-	return attribute_statistics_update_internal(reloid, attname, attnum,
-												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]
-		);
-}
-
-/*
- * Workhorse function for attribute_statistics_update.
- */
-static bool
-attribute_statistics_update_internal(Oid reloid,
-									 const char *attname, AttrNumber attnum,
-									 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)
+attribute_statistics_update(Oid reloid,
+							const char *attname, AttrNumber attnum,
+							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;
@@ -725,14 +635,91 @@ pg_clear_attribute_stats(PG_FUNCTION_ARGS)
 Datum
 pg_restore_attribute_stats(PG_FUNCTION_ARGS)
 {
-	NullableDatum positional_args[ATTARG_NUM_ATTARGS];
+	NullableDatum args[ATTARG_NUM_ATTARGS];
 	bool		result = true;
+	char	   *nspname;
+	char	   *relname;
+	Oid			reloid;
+	char	   *attname;
+	AttrNumber	attnum;
+	bool		inherited;
 
-	if (!stats_fill_args_from_arg_pairs(fcinfo, positional_args,
+	if (!stats_fill_args_from_arg_pairs(fcinfo, args,
 										attarginfo))
 		result = false;
 
-	if (!attribute_statistics_update(positional_args))
+	stats_check_required_arg(&args[ATTARG_ATTRELSCHEMA], attarginfo[ATTARG_ATTRELSCHEMA].argname);
+	stats_check_required_arg(&args[ATTARG_ATTRELNAME], attarginfo[ATTARG_ATTRELNAME].argname);
+
+	nspname = TextDatumGetCString(args[ATTARG_ATTRELSCHEMA].value);
+	relname = TextDatumGetCString(args[ATTARG_ATTRELNAME].value);
+
+	stats_check_recovery(ERROR);
+
+	/* lock before looking up attribute */
+	reloid = stats_check_lock_relation(nspname, relname);
+
+	/* user can specify either attname or attnum, but not both */
+	if (!args[ATTARG_ATTNAME].isnull)
+	{
+		if (!args[ATTARG_ATTNUM].isnull)
+			ereport(ERROR,
+					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+					 errmsg("cannot specify both \"%s\" and \"%s\"", "attname", "attnum")));
+		attname = TextDatumGetCString(args[ATTARG_ATTNAME].value);
+		attnum = get_attnum(reloid, attname);
+		/* note that this test covers attisdropped cases too: */
+		if (attnum == InvalidAttrNumber)
+			ereport(ERROR,
+					(errcode(ERRCODE_UNDEFINED_COLUMN),
+					 errmsg("column \"%s\" of relation \"%s\" does not exist",
+							attname, relname)));
+	}
+	else if (!args[ATTARG_ATTNUM].isnull)
+	{
+		attnum = DatumGetInt16(args[ATTARG_ATTNUM].value);
+		attname = get_attname(reloid, attnum, true);
+		/* annoyingly, get_attname doesn't check attisdropped */
+		if (attname == NULL ||
+			!SearchSysCacheExistsAttName(reloid, attname))
+			ereport(ERROR,
+					(errcode(ERRCODE_UNDEFINED_COLUMN),
+					 errmsg("column %d of relation \"%s\" does not exist",
+							attnum, relname)));
+	}
+	else
+	{
+		ereport(ERROR,
+				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+				 errmsg("must specify either \"%s\" or \"%s\"", "attname", "attnum")));
+		attname = NULL;			/* keep compiler quiet */
+		attnum = 0;
+	}
+
+	if (attnum < 0)
+		ereport(ERROR,
+				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+				 errmsg("cannot modify statistics on system column \"%s\"",
+						attname)));
+
+	stats_check_required_arg(&args[ATTARG_INHERITED], attarginfo[ATTARG_INHERITED].argname);
+	inherited = DatumGetBool(args[ATTARG_INHERITED].value);
+
+	if (!attribute_statistics_update(reloid, attname, attnum, 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]))
 		result = false;
 
 	PG_RETURN_BOOL(result);
@@ -793,18 +780,16 @@ import_attribute_statistics(Relation rel, AttrNumber attnum, bool inherited,
 				 errmsg("column %d of relation \"%s\" does not exist",
 						attnum, relname)));
 
-	return attribute_statistics_update_internal(reloid, attname, attnum,
-												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);
+	return attribute_statistics_update(reloid, attname, attnum, 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);
 }
 
 /*
-- 
2.50.1 (Apple Git-155)

