From 3f857611b69c95f325aba5ed8049e376326db8fd Mon Sep 17 00:00:00 2001 From: Corey Huinker Date: Mon, 22 Jun 2026 13:43:37 -0400 Subject: [PATCH v2 3/7] New function: stats_acquire_relation_lock(). Introduce a new funciton, stats_acquire_relation_lock() which will perform the RangeVarGetRelidExtended() call used to verify the correct reloid of the relation, verify that the caller has the correct permissions for the operation, and acquiring the lock. Additionally, it will check RecoveryInProgress() before acquiring a lock because we can't acquire locks during recovery, let alone set statistics. This function will be used by all of the callers of relation_statistics_update() and attribute_statistics_update(). --- src/include/statistics/stat_utils.h | 2 ++ src/backend/statistics/stat_utils.c | 26 ++++++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/src/include/statistics/stat_utils.h b/src/include/statistics/stat_utils.h index 74da7790579..bcdfa616ce6 100644 --- a/src/include/statistics/stat_utils.h +++ b/src/include/statistics/stat_utils.h @@ -37,6 +37,8 @@ extern bool stats_check_arg_pair(FunctionCallInfo fcinfo, extern void RangeVarCallbackForStats(const RangeVar *relation, Oid relId, Oid oldRelId, void *arg); +extern Oid stats_acquire_relation_lock(const char *nspname, const char *relname); + extern bool stats_fill_fcinfo_from_arg_pairs(FunctionCallInfo pairs_fcinfo, FunctionCallInfo positional_fcinfo, struct StatsArgInfo *arginfo); diff --git a/src/backend/statistics/stat_utils.c b/src/backend/statistics/stat_utils.c index a673e3c704b..75792ff966a 100644 --- a/src/backend/statistics/stat_utils.c +++ b/src/backend/statistics/stat_utils.c @@ -26,6 +26,7 @@ #include "catalog/pg_statistic.h" #include "funcapi.h" #include "miscadmin.h" +#include "nodes/makefuncs.h" #include "nodes/nodeFuncs.h" #include "statistics/stat_utils.h" #include "storage/lmgr.h" @@ -753,3 +754,28 @@ statatt_init_empty_tuple(Oid reloid, int16 attnum, bool inherited, nulls[Anum_pg_statistic_stacoll1 + slotnum - 1] = false; } } + +/* + * Convenience routine to encapsulate the RangeVarGetRelidExtended() + * that all external callers must make before calling + * relation_statistics_update() or attribute_statistics_update(). + * + * Check for recovery in progress before acquiring any locks. + */ +Oid +stats_acquire_relation_lock(const char *nspname, const char *relname) +{ + Oid reloid; + Oid locked_table = InvalidOid; + + 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((char *) nspname, (char *) relname, -1), + ShareUpdateExclusiveLock, 0, + RangeVarCallbackForStats, &locked_table); + return reloid; +} -- 2.54.0