From 6cda28a063bdb854fbfb42dcdce2650730bdeea2 Mon Sep 17 00:00:00 2001
From: Corey Huinker <corey.huinker@gmail.com>
Date: Mon, 22 Jun 2026 14:05:32 -0400
Subject: [PATCH v2 5/7] Rename import_relation_statistics() to
 relation_statistics_update().

Rename existing relation_statistics_update() to update_relstats() and
change the call signature to have the relation oid. All callers now
independently resovle the reloid via stats_acquire_relation_lock().
---
 src/include/statistics/relation_stats.h |   2 +-
 src/backend/statistics/relation_stats.c | 194 +++++++++++++-----------
 contrib/postgres_fdw/postgres_fdw.c     |   2 +-
 3 files changed, 105 insertions(+), 93 deletions(-)

diff --git a/src/include/statistics/relation_stats.h b/src/include/statistics/relation_stats.h
index f68a1a755a1..423ff8961f2 100644
--- a/src/include/statistics/relation_stats.h
+++ b/src/include/statistics/relation_stats.h
@@ -14,7 +14,7 @@
 
 #include "access/genam.h"
 
-bool import_relation_statistics(Relation rel, const char *relpages,
+bool relation_statistics_update(Relation rel, const char *relpages,
 								const char *reltuples, const char *relallvisible,
 								const char *relallfrozen);
 
diff --git a/src/backend/statistics/relation_stats.c b/src/backend/statistics/relation_stats.c
index 9c308ee50e5..2e07df78d8b 100644
--- a/src/backend/statistics/relation_stats.c
+++ b/src/backend/statistics/relation_stats.c
@@ -32,8 +32,8 @@
 
 
 /*
- * Positional argument numbers, names, and types for
- * relation_statistics_update().
+ * Positional argument numbers, names, and types for positional_fcinfo
+ * used by update_relstats().
  */
 
 enum relation_stats_argnum
@@ -58,18 +58,15 @@ static struct StatsArgInfo relarginfo[] =
 	[NUM_RELATION_STATS_ARGS] = {0}
 };
 
-static bool relation_statistics_update(FunctionCallInfo fcinfo);
+static bool update_relstats(Oid reloid, FunctionCallInfo fcinfo);
 
 /*
  * Internal function for modifying statistics for a relation.
  */
 static bool
-relation_statistics_update(FunctionCallInfo fcinfo)
+update_relstats(Oid reloid, FunctionCallInfo fcinfo)
 {
 	bool		result = true;
-	char	   *nspname;
-	char	   *relname;
-	Oid			reloid;
 	Relation	crel;
 	BlockNumber relpages = 0;
 	bool		update_relpages = false;
@@ -85,23 +82,6 @@ relation_statistics_update(FunctionCallInfo fcinfo)
 	Datum		values[4] = {0};
 	bool		nulls[4] = {0};
 	int			nreplaces = 0;
-	Oid			locked_table = InvalidOid;
-
-	stats_check_required_arg(fcinfo, relarginfo, RELSCHEMA_ARG);
-	stats_check_required_arg(fcinfo, relarginfo, RELNAME_ARG);
-
-	nspname = TextDatumGetCString(PG_GETARG_DATUM(RELSCHEMA_ARG));
-	relname = TextDatumGetCString(PG_GETARG_DATUM(RELNAME_ARG));
-
-	if (RecoveryInProgress())
-		ereport(ERROR,
-				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
-				 errmsg("recovery is in progress"),
-				 errhint("Statistics cannot be modified during recovery.")));
-
-	reloid = RangeVarGetRelidExtended(makeRangeVar(nspname, relname, -1),
-									  ShareUpdateExclusiveLock, 0,
-									  RangeVarCallbackForStats, &locked_table);
 
 	if (!PG_ARGISNULL(RELPAGES_ARG))
 	{
@@ -203,24 +183,35 @@ relation_statistics_update(FunctionCallInfo fcinfo)
 Datum
 pg_clear_relation_stats(PG_FUNCTION_ARGS)
 {
-	LOCAL_FCINFO(newfcinfo, 6);
+	LOCAL_FCINFO(positional_fcinfo, NUM_RELATION_STATS_ARGS);
+	Oid			reloid;
+	char	   *nspname;
+	char	   *relname;
 
-	InitFunctionCallInfoData(*newfcinfo, NULL, 6, InvalidOid, NULL, NULL);
+	InitFunctionCallInfoData(*positional_fcinfo, NULL, 6, InvalidOid, NULL, NULL);
 
-	newfcinfo->args[0].value = PG_GETARG_DATUM(0);
-	newfcinfo->args[0].isnull = PG_ARGISNULL(0);
-	newfcinfo->args[1].value = PG_GETARG_DATUM(1);
-	newfcinfo->args[1].isnull = PG_ARGISNULL(1);
-	newfcinfo->args[2].value = UInt32GetDatum(0);
-	newfcinfo->args[2].isnull = false;
-	newfcinfo->args[3].value = Float4GetDatum(-1.0);
-	newfcinfo->args[3].isnull = false;
-	newfcinfo->args[4].value = UInt32GetDatum(0);
-	newfcinfo->args[4].isnull = false;
-	newfcinfo->args[5].value = UInt32GetDatum(0);
-	newfcinfo->args[5].isnull = false;
+	positional_fcinfo->args[RELSCHEMA_ARG].value = PG_GETARG_DATUM(0);
+	positional_fcinfo->args[RELSCHEMA_ARG].isnull = PG_ARGISNULL(0);
+	positional_fcinfo->args[RELNAME_ARG].value = PG_GETARG_DATUM(1);
+	positional_fcinfo->args[RELNAME_ARG].isnull = PG_ARGISNULL(1);
+	positional_fcinfo->args[RELPAGES_ARG].value = UInt32GetDatum(0);
+	positional_fcinfo->args[RELPAGES_ARG].isnull = false;
+	positional_fcinfo->args[RELTUPLES_ARG].value = Float4GetDatum(-1.0);
+	positional_fcinfo->args[RELTUPLES_ARG].isnull = false;
+	positional_fcinfo->args[RELALLVISIBLE_ARG].value = UInt32GetDatum(0);
+	positional_fcinfo->args[RELALLVISIBLE_ARG].isnull = false;
+	positional_fcinfo->args[RELALLFROZEN_ARG].value = UInt32GetDatum(0);
+	positional_fcinfo->args[RELALLFROZEN_ARG].isnull = false;
 
-	relation_statistics_update(newfcinfo);
+	stats_check_required_arg(positional_fcinfo, relarginfo, RELSCHEMA_ARG);
+	stats_check_required_arg(positional_fcinfo, relarginfo, RELNAME_ARG);
+
+	nspname = TextDatumGetCString(positional_fcinfo->args[RELSCHEMA_ARG].value);
+	relname = TextDatumGetCString(positional_fcinfo->args[RELNAME_ARG].value);
+
+	reloid = stats_acquire_relation_lock(nspname, relname);
+
+	update_relstats(reloid, positional_fcinfo);
 	PG_RETURN_VOID();
 }
 
@@ -229,6 +220,9 @@ pg_restore_relation_stats(PG_FUNCTION_ARGS)
 {
 	LOCAL_FCINFO(positional_fcinfo, NUM_RELATION_STATS_ARGS);
 	bool		result = true;
+	Oid			reloid;
+	char	   *nspname;
+	char	   *relname;
 
 	InitFunctionCallInfoData(*positional_fcinfo, NULL,
 							 NUM_RELATION_STATS_ARGS,
@@ -238,7 +232,15 @@ pg_restore_relation_stats(PG_FUNCTION_ARGS)
 										  relarginfo))
 		result = false;
 
-	if (!relation_statistics_update(positional_fcinfo))
+	stats_check_required_arg(positional_fcinfo, relarginfo, RELSCHEMA_ARG);
+	stats_check_required_arg(positional_fcinfo, relarginfo, RELNAME_ARG);
+
+	nspname = TextDatumGetCString(positional_fcinfo->args[RELSCHEMA_ARG].value);
+	relname = TextDatumGetCString(positional_fcinfo->args[RELNAME_ARG].value);
+
+	reloid = stats_acquire_relation_lock(nspname, relname);
+
+	if (!update_relstats(reloid, positional_fcinfo))
 		result = false;
 
 	PG_RETURN_BOOL(result);
@@ -248,92 +250,102 @@ pg_restore_relation_stats(PG_FUNCTION_ARGS)
  * Convenience routine to parse BlockNumber values, and emit a warning
  * on parse errors.
  *
- * Returns 0 if the value is NULL or invalid.
+ * Returns Datum of 0 if the value is NULL or invalid.
  */
-static BlockNumber
+static Datum
 str_to_blocknumber(const char *s)
 {
-	const BlockNumber default_value = 0;
+	BlockNumber result = 0;
 
-	BlockNumber result;
-	ErrorSaveContext escontext = {T_ErrorSaveContext};
-
-	if (!s)
-		return default_value;
-
-	result = uint32in_subr(s, NULL, "BlockNumber", (Node *) &escontext);
-
-	if (escontext.error_occurred)
+	if (s)
 	{
-		escontext.error_data->elevel = WARNING;
-		ThrowErrorData(escontext.error_data);
-		FreeErrorData(escontext.error_data);
+		BlockNumber scratch_result;
+		ErrorSaveContext escontext = {T_ErrorSaveContext};
 
-		return default_value;
+		scratch_result = uint32in_subr(s, NULL, "BlockNumber", (Node *) &escontext);
+
+		if (escontext.error_occurred)
+		{
+			escontext.error_data->elevel = WARNING;
+			ThrowErrorData(escontext.error_data);
+			FreeErrorData(escontext.error_data);
+		}
+		else
+			result = scratch_result;
 	}
 
-	return result;
+	return UInt32GetDatum(result);
 }
 
 /*
  * Convenience routine to parse float values, and emit a warning on parse
  * errors.
  *
- * Returns -1.0 if the value is NULL or invalid.
+ * Returns Datum of -1.0 if the value is NULL or invalid.
  */
-static float
+static Datum
 str_to_float(const char *s)
 {
-	const float default_value = -1.0;
+	float result = -1.0;
 
-	float		result;
-
-	ErrorSaveContext escontext = {T_ErrorSaveContext};
-
-	if (!s)
-		return default_value;
-
-	result = float4in_internal((char *) s, NULL, "float", s, (Node *) &escontext);
-
-	if (escontext.error_occurred)
+	if (s)
 	{
-		escontext.error_data->elevel = WARNING;
-		ThrowErrorData(escontext.error_data);
-		FreeErrorData(escontext.error_data);
-		return default_value;
+		ErrorSaveContext escontext = {T_ErrorSaveContext};
+
+		float	scratch_result;
+
+		scratch_result = float4in_internal((char *) s, NULL, "float", s, (Node *) &escontext);
+
+		if (escontext.error_occurred)
+		{
+			escontext.error_data->elevel = WARNING;
+			ThrowErrorData(escontext.error_data);
+			FreeErrorData(escontext.error_data);
+		}
+		else
+			result = scratch_result;
 	}
 
-	return result;
+	return Float4GetDatum(result);
 }
 
 /*
  * Import relation statistics from regular string inputs.
  */
 bool
-import_relation_statistics(Relation rel, const char *relpages,
+relation_statistics_update(Relation rel, const char *relpages,
 						   const char *reltuples, const char *relallvisible,
 						   const char *relallfrozen)
 {
-	LOCAL_FCINFO(newfcinfo, NUM_RELATION_STATS_ARGS);
+	LOCAL_FCINFO(positional_fcinfo, NUM_RELATION_STATS_ARGS);
+	Oid			reloid;
+	char	   *nspname;
+	char	   *relname;
 
-	InitFunctionCallInfoData(*newfcinfo, NULL, NUM_RELATION_STATS_ARGS, InvalidOid, NULL, NULL);
+	InitFunctionCallInfoData(*positional_fcinfo, NULL, NUM_RELATION_STATS_ARGS,
+							 InvalidOid, NULL, NULL);
+
+	nspname = get_namespace_name(RelationGetNamespace(rel));
+	relname = RelationGetRelationName(rel);
+
+	reloid = stats_acquire_relation_lock(nspname, relname);
 
 	/*
 	 * Convert all string inputs to their required datatypes. NULL values are
 	 * left as the default.
 	 */
-	newfcinfo->args[RELSCHEMA_ARG].value = CStringGetTextDatum(get_namespace_name(RelationGetNamespace(rel)));
-	newfcinfo->args[RELSCHEMA_ARG].isnull = false;
-	newfcinfo->args[RELNAME_ARG].value = CStringGetTextDatum(RelationGetRelationName(rel));
-	newfcinfo->args[RELNAME_ARG].isnull = false;
-	newfcinfo->args[RELPAGES_ARG].value = UInt32GetDatum(str_to_blocknumber(relpages));
-	newfcinfo->args[RELPAGES_ARG].isnull = false;
-	newfcinfo->args[RELTUPLES_ARG].value = Float4GetDatum(str_to_float(reltuples));
-	newfcinfo->args[RELTUPLES_ARG].isnull = false;
-	newfcinfo->args[RELALLVISIBLE_ARG].value = UInt32GetDatum(str_to_blocknumber(relallvisible));
-	newfcinfo->args[RELALLVISIBLE_ARG].isnull = false;
-	newfcinfo->args[RELALLFROZEN_ARG].value = UInt32GetDatum(str_to_blocknumber(relallfrozen));
-	newfcinfo->args[RELALLFROZEN_ARG].isnull = false;
+	positional_fcinfo->args[RELSCHEMA_ARG].value = CStringGetTextDatum(nspname);
+	positional_fcinfo->args[RELSCHEMA_ARG].isnull = false;
+	positional_fcinfo->args[RELNAME_ARG].value = CStringGetTextDatum(relname);
+	positional_fcinfo->args[RELNAME_ARG].isnull = false;
+	positional_fcinfo->args[RELPAGES_ARG].value = str_to_blocknumber(relpages);
+	positional_fcinfo->args[RELPAGES_ARG].isnull = false;
+	positional_fcinfo->args[RELTUPLES_ARG].value = str_to_float(reltuples);
+	positional_fcinfo->args[RELTUPLES_ARG].isnull = false;
+	positional_fcinfo->args[RELALLVISIBLE_ARG].value = str_to_blocknumber(relallvisible);
+	positional_fcinfo->args[RELALLVISIBLE_ARG].isnull = false;
+	positional_fcinfo->args[RELALLFROZEN_ARG].value = str_to_blocknumber(relallfrozen);
+	positional_fcinfo->args[RELALLFROZEN_ARG].isnull = false;
 
-	return relation_statistics_update(newfcinfo);
+	return update_relstats(reloid, positional_fcinfo);
 }
diff --git a/contrib/postgres_fdw/postgres_fdw.c b/contrib/postgres_fdw/postgres_fdw.c
index 8aa589d5a56..1d203f5fcf5 100644
--- a/contrib/postgres_fdw/postgres_fdw.c
+++ b/contrib/postgres_fdw/postgres_fdw.c
@@ -6086,7 +6086,7 @@ import_fetched_statistics(Relation relation,
 	if (!PQgetisnull(remstats->rel, 0, RELSTATS_RELTUPLES))
 		reltuples = PQgetvalue(remstats->rel, 0, RELSTATS_RELTUPLES);
 
-	if (!import_relation_statistics(relation, relpages, reltuples,
+	if (!relation_statistics_update(relation, relpages, reltuples,
 									NULL, NULL))
 	{
 		ereport(WARNING,
-- 
2.54.0

