summaryrefslogtreecommitdiff
path: root/src/backend/statistics/stat_utils.c
diff options
context:
space:
mode:
authorJeff Davis <jdavis@postgresql.org>2024-10-11 16:55:11 -0700
committerJeff Davis <jdavis@postgresql.org>2024-10-11 16:55:11 -0700
commite839c8ecc9352b7754e74f19ace013c0c0d18613 (patch)
tree881e69557ddddebec18104dc286c1ef160d8f909 /src/backend/statistics/stat_utils.c
parent6f782a2a1738ab96ee948a4ab33ca3defd39327b (diff)
Create functions pg_set_relation_stats, pg_clear_relation_stats.
These functions are used to tweak statistics on any relation, provided that the user has MAINTAIN privilege on the relation, or is the database owner. Bump catalog version. Author: Corey Huinker Discussion: https://postgr.es/m/CADkLM=eErgzn7ECDpwFcptJKOk9SxZEk5Pot4d94eVTZsvj3gw@mail.gmail.com
Diffstat (limited to 'src/backend/statistics/stat_utils.c')
-rw-r--r--src/backend/statistics/stat_utils.c94
1 files changed, 94 insertions, 0 deletions
diff --git a/src/backend/statistics/stat_utils.c b/src/backend/statistics/stat_utils.c
new file mode 100644
index 00000000000..4babed2e5d7
--- /dev/null
+++ b/src/backend/statistics/stat_utils.c
@@ -0,0 +1,94 @@
+/*-------------------------------------------------------------------------
+ * stat_utils.c
+ *
+ * PostgreSQL statistics manipulation utilities.
+ *
+ * Code supporting the direct manipulation of statistics.
+ *
+ * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/backend/statistics/stat_utils.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#include "access/relation.h"
+#include "catalog/pg_database.h"
+#include "miscadmin.h"
+#include "statistics/stat_utils.h"
+#include "utils/array.h"
+#include "utils/builtins.h"
+#include "utils/acl.h"
+#include "utils/rel.h"
+
+/*
+ * Ensure that a given argument is not null.
+ */
+void
+stats_check_required_arg(FunctionCallInfo fcinfo,
+ struct StatsArgInfo *arginfo,
+ int argnum)
+{
+ if (PG_ARGISNULL(argnum))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("\"%s\" cannot be NULL",
+ arginfo[argnum].argname)));
+}
+
+/*
+ * Lock relation in ShareUpdateExclusive mode, check privileges, and close the
+ * relation (but retain the lock).
+ *
+ * A role has privileges to set statistics on the relation if any of the
+ * following are true:
+ * - the role owns the current database and the relation is not shared
+ * - the role has the MAINTAIN privilege on the relation
+ */
+void
+stats_lock_check_privileges(Oid reloid)
+{
+ Relation rel = relation_open(reloid, ShareUpdateExclusiveLock);
+ const char relkind = rel->rd_rel->relkind;
+
+ /* All of the types that can be used with ANALYZE, plus indexes */
+ switch (relkind)
+ {
+ case RELKIND_RELATION:
+ case RELKIND_INDEX:
+ case RELKIND_MATVIEW:
+ case RELKIND_FOREIGN_TABLE:
+ case RELKIND_PARTITIONED_TABLE:
+ case RELKIND_PARTITIONED_INDEX:
+ break;
+ default:
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("cannot modify statistics for relation \"%s\"",
+ RelationGetRelationName(rel)),
+ errdetail_relkind_not_supported(rel->rd_rel->relkind)));
+ }
+
+ if (rel->rd_rel->relisshared)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("cannot modify statistics for shared relation")));
+
+ if (!object_ownercheck(DatabaseRelationId, MyDatabaseId, GetUserId()))
+ {
+ AclResult aclresult = pg_class_aclcheck(RelationGetRelid(rel),
+ GetUserId(),
+ ACL_MAINTAIN);
+
+ if (aclresult != ACLCHECK_OK)
+ aclcheck_error(aclresult,
+ get_relkind_objtype(rel->rd_rel->relkind),
+ NameStr(rel->rd_rel->relname));
+ }
+
+ relation_close(rel, NoLock);
+}