1/*-------------------------------------------------------------------------
4 * PostgreSQL statistics manipulation utilities.
6 * Code supporting the direct manipulation of statistics.
8 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
9 * Portions Copyright (c) 1994, Regents of the University of California
12 * src/backend/statistics/stat_utils.c
14 *-------------------------------------------------------------------------
34 * Ensure that a given argument is not null.
43 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
44 errmsg(
"argument \"%s\" must not be null",
45 arginfo[argnum].argname)));
49 * Check that argument is either NULL or a one dimensional array with no
52 * If a problem is found, emit a WARNING, and return false. Otherwise return
70 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
71 errmsg(
"argument \"%s\" must not be a multidimensional array",
72 arginfo[argnum].argname)));
79 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
80 errmsg(
"argument \"%s\" array must not contain null values",
81 arginfo[argnum].argname)));
89 * Enforce parameter pairs that must be specified together (or not at all) for
90 * a particular stakind, such as most_common_vals and most_common_freqs for
93 * If a problem is found, emit a WARNING, and return false. Otherwise return
99 int argnum1,
int argnum2)
106 int nullarg =
PG_ARGISNULL(argnum1) ? argnum1 : argnum2;
107 int otherarg =
PG_ARGISNULL(argnum1) ? argnum2 : argnum1;
110 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
111 errmsg(
"argument \"%s\" must be specified when argument \"%s\" is specified",
112 arginfo[nullarg].argname,
113 arginfo[otherarg].argname)));
122 * Lock relation in ShareUpdateExclusive mode, check privileges, and close the
123 * relation (but retain the lock).
125 * A role has privileges to set statistics on the relation if any of the
126 * following are true:
127 * - the role owns the current database and the relation is not shared
128 * - the role has the MAINTAIN privilege on the relation
134 Oid table_oid = reloid;
139 * For indexes, we follow the locking behavior in do_analyze_rel() and
140 * check_lock_if_inplace_updateable_rel(), which is to lock the table
141 * first in ShareUpdateExclusive mode and then the index in AccessShare
144 * Partitioned indexes are treated differently than normal indexes in
145 * check_lock_if_inplace_updateable_rel(), so we take a
146 * ShareUpdateExclusive lock on both the partitioned table and the
156 case RELKIND_PARTITIONED_INDEX:
167 /* the relkinds that can be used with ANALYZE */
168 switch (
table->rd_rel->relkind)
170 case RELKIND_RELATION:
171 case RELKIND_MATVIEW:
172 case RELKIND_FOREIGN_TABLE:
173 case RELKIND_PARTITIONED_TABLE:
177 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
178 errmsg(
"cannot modify statistics for relation \"%s\"",
192 /* retain lock on index */
196 if (
table->rd_rel->relisshared)
198 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
199 errmsg(
"cannot modify statistics for shared relation")));
213 /* retain lock on table */
218 * Lookup relation oid from schema and relation name.
231 errmsg(
"relation \"%s.%s\" does not exist",
239 * Find the argument number for the given argument name, returning -1 if not
247 for (argnum = 0; arginfo[argnum].
argname != NULL; argnum++)
252 (
errmsg(
"unrecognized argument name: \"%s\"", argname)));
258 * Ensure that a given argument matched the expected type.
263 if (argtype != expectedtype)
266 (
errmsg(
"argument \"%s\" has type %s, expected type %s",
276 * Translate variadic argument pairs from 'pairs_fcinfo' into a
277 * 'positional_fcinfo' appropriate for calling relation_statistics_update() or
278 * attribute_statistics_update() with positional arguments.
280 * Caller should have already initialized positional_fcinfo with a size
281 * appropriate for calling the intended positional function, and arginfo
282 * should also match the intended positional function.
295 /* clear positional args */
296 for (
int i = 0; arginfo[
i].
argname != NULL;
i++)
307 errmsg(
"variadic arguments must be name/value pairs"),
308 errhint(
"Provide an even number of variadic arguments that can be divided into pairs."));
311 * For each argument name/value pair, find corresponding positional
312 * argument for the argument name, and assign the argument value to
315 for (
int i = 0;
i < nargs;
i += 2)
322 (
errmsg(
"name at variadic position %d is null",
i + 1)));
326 (
errmsg(
"name at variadic position %d has type %s, expected type %s",
336 * The 'version' argument is a special case, not handled by arginfo
337 * because it's not a valid positional argument.
339 * For now, 'version' is accepted but ignored. In the future it can be
340 * used to interpret older statistics properly.
348 arginfo[argnum].argtype))
355 positional_fcinfo->
args[argnum].
isnull =
false;
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
bool object_ownercheck(Oid classid, Oid objectid, Oid roleid)
AclResult pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode)
#define DatumGetArrayTypeP(X)
bool array_contains_nulls(ArrayType *array)
#define TextDatumGetCString(d)
#define OidIsValid(objectId)
int errhint(const char *fmt,...)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
#define PG_GETARG_DATUM(n)
int extract_variadic_args(FunctionCallInfo fcinfo, int variadic_start, bool convert_unknown, Datum **args, Oid **types, bool **nulls)
Assert(PointerIsAligned(start, uint64))
Oid IndexGetRelation(Oid indexId, bool missing_ok)
#define ShareUpdateExclusiveLock
char get_rel_relkind(Oid relid)
Oid get_relname_relid(const char *relname, Oid relnamespace)
Oid LookupExplicitNamespace(const char *nspname, bool missing_ok)
ObjectType get_relkind_objtype(char relkind)
int errdetail_relkind_not_supported(char relkind)
static const struct lconv_member_info table[]
#define ERRCODE_UNDEFINED_TABLE
int pg_strcasecmp(const char *s1, const char *s2)
#define RelationGetRelid(relation)
#define RelationGetRelationName(relation)
void relation_close(Relation relation, LOCKMODE lockmode)
Relation relation_open(Oid relationId, LOCKMODE lockmode)
bool stats_fill_fcinfo_from_arg_pairs(FunctionCallInfo pairs_fcinfo, FunctionCallInfo positional_fcinfo, struct StatsArgInfo *arginfo)
static int get_arg_by_name(const char *argname, struct StatsArgInfo *arginfo)
static bool stats_check_arg_type(const char *argname, Oid argtype, Oid expectedtype)
bool stats_check_arg_array(FunctionCallInfo fcinfo, struct StatsArgInfo *arginfo, int argnum)
void stats_check_required_arg(FunctionCallInfo fcinfo, struct StatsArgInfo *arginfo, int argnum)
void stats_lock_check_privileges(Oid reloid)
Oid stats_lookup_relid(const char *nspname, const char *relname)
bool stats_check_arg_pair(FunctionCallInfo fcinfo, struct StatsArgInfo *arginfo, int argnum1, int argnum2)
NullableDatum args[FLEXIBLE_ARRAY_MEMBER]