1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
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/acl.h"
#include "utils/array.h"
#include "utils/builtins.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);
}
|