PostgreSQL Source Code git master
Loading...
Searching...
No Matches
statscmds.c File Reference
#include "postgres.h"
#include "access/htup_details.h"
#include "access/relation.h"
#include "access/table.h"
#include "catalog/catalog.h"
#include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/namespace.h"
#include "catalog/objectaccess.h"
#include "catalog/pg_namespace.h"
#include "catalog/pg_statistic_ext.h"
#include "catalog/pg_statistic_ext_data.h"
#include "commands/comment.h"
#include "commands/defrem.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h"
#include "optimizer/optimizer.h"
#include "statistics/statistics.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/inval.h"
#include "utils/lsyscache.h"
#include "utils/rel.h"
#include "utils/syscache.h"
#include "utils/typcache.h"
Include dependency graph for statscmds.c:

Go to the source code of this file.

Functions

static charChooseExtendedStatisticName (const char *name1, const char *name2, const char *label, Oid namespaceid)
 
static charChooseExtendedStatisticNameAddition (List *exprs)
 
static int compare_int16 (const void *a, const void *b)
 
ObjectAddress CreateStatistics (CreateStatsStmt *stmt, bool check_rights)
 
ObjectAddress AlterStatistics (AlterStatsStmt *stmt)
 
void RemoveStatisticsDataById (Oid statsOid, bool inh)
 
void RemoveStatisticsById (Oid statsOid)
 
Oid StatisticsGetRelation (Oid statId, bool missing_ok)
 

Function Documentation

◆ AlterStatistics()

ObjectAddress AlterStatistics ( AlterStatsStmt stmt)

Definition at line 669 of file statscmds.c.

670{
671 Relation rel;
672 Oid stxoid;
678 ObjectAddress address;
679 int newtarget = 0;
681
682 /* -1 was used in previous versions for the default setting */
683 if (stmt->stxstattarget && intVal(stmt->stxstattarget) != -1)
684 {
685 newtarget = intVal(stmt->stxstattarget);
686 newtarget_default = false;
687 }
688 else
689 newtarget_default = true;
690
692 {
693 /* Limit statistics target to a sane range */
694 if (newtarget < 0)
695 {
698 errmsg("statistics target %d is too low",
699 newtarget)));
700 }
702 {
706 errmsg("lowering statistics target to %d",
707 newtarget)));
708 }
709 }
710
711 /* lookup OID of the statistics object */
712 stxoid = get_statistics_object_oid(stmt->defnames, stmt->missing_ok);
713
714 /*
715 * If we got here and the OID is not valid, it means the statistics object
716 * does not exist, but the command specified IF EXISTS. So report this as
717 * a simple NOTICE and we're done.
718 */
719 if (!OidIsValid(stxoid))
720 {
721 char *schemaname;
722 char *statname;
723
724 Assert(stmt->missing_ok);
725
726 DeconstructQualifiedName(stmt->defnames, &schemaname, &statname);
727
728 if (schemaname)
730 (errmsg("statistics object \"%s.%s\" does not exist, skipping",
731 schemaname, statname)));
732 else
734 (errmsg("statistics object \"%s\" does not exist, skipping",
735 statname)));
736
738 }
739
740 /* Search pg_statistic_ext */
742
745 elog(ERROR, "cache lookup failed for extended statistics object %u", stxoid);
746
747 /* Must be owner of the existing statistics object */
750 NameListToString(stmt->defnames));
751
752 /* Build new tuple. */
753 memset(repl_val, 0, sizeof(repl_val));
754 memset(repl_null, false, sizeof(repl_null));
755 memset(repl_repl, false, sizeof(repl_repl));
756
757 /* replace the stxstattarget column */
761 else
763
766
767 /* Update system catalog. */
768 CatalogTupleUpdate(rel, &newtup->t_self, newtup);
769
771
773
774 /*
775 * NOTE: because we only support altering the statistics target, not the
776 * other fields, there is no need to update dependencies.
777 */
778
781
783
784 return address;
785}
@ ACLCHECK_NOT_OWNER
Definition acl.h:186
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition aclchk.c:2672
bool object_ownercheck(Oid classid, Oid objectid, Oid roleid)
Definition aclchk.c:4156
#define Assert(condition)
Definition c.h:1002
#define OidIsValid(objectId)
Definition c.h:917
int errcode(int sqlerrcode)
Definition elog.c:875
#define WARNING
Definition elog.h:37
#define ERROR
Definition elog.h:40
#define elog(elevel,...)
Definition elog.h:228
#define NOTICE
Definition elog.h:36
#define ereport(elevel,...)
Definition elog.h:152
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, const Datum *replValues, const bool *replIsnull, const bool *doReplace)
Definition heaptuple.c:1118
void heap_freetuple(HeapTuple htup)
Definition heaptuple.c:1372
#define HeapTupleIsValid(tuple)
Definition htup.h:78
#define stmt
void CatalogTupleUpdate(Relation heapRel, const ItemPointerData *otid, HeapTuple tup)
Definition indexing.c:313
#define RowExclusiveLock
Definition lockdefs.h:38
Oid GetUserId(void)
Definition miscinit.c:470
char * NameListToString(const List *names)
Definition namespace.c:3666
Oid get_statistics_object_oid(List *names, bool missing_ok)
Definition namespace.c:2644
void DeconstructQualifiedName(const List *names, char **nspname_p, char **objname_p)
Definition namespace.c:3373
static char * errmsg
#define InvokeObjectPostAlterHook(classId, objectId, subId)
const ObjectAddress InvalidObjectAddress
#define ObjectAddressSet(addr, class_id, object_id)
@ OBJECT_STATISTIC_EXT
static Datum Int16GetDatum(int16 X)
Definition postgres.h:172
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:252
uint64_t Datum
Definition postgres.h:70
unsigned int Oid
static int fb(int x)
#define RelationGetDescr(relation)
Definition rel.h:542
void ReleaseSysCache(HeapTuple tuple)
Definition syscache.c:265
HeapTuple SearchSysCache1(SysCacheIdentifier cacheId, Datum key1)
Definition syscache.c:221
void table_close(Relation relation, LOCKMODE lockmode)
Definition table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition table.c:40
#define MAX_STATISTICS_TARGET
Definition vacuum.h:350
#define intVal(v)
Definition value.h:79

References aclcheck_error(), ACLCHECK_NOT_OWNER, Assert, CatalogTupleUpdate(), DeconstructQualifiedName(), elog, ereport, errcode(), errmsg, ERROR, fb(), get_statistics_object_oid(), GetUserId(), heap_freetuple(), heap_modify_tuple(), HeapTupleIsValid, Int16GetDatum(), intVal, InvalidObjectAddress, InvokeObjectPostAlterHook, MAX_STATISTICS_TARGET, NameListToString(), NOTICE, object_ownercheck(), OBJECT_STATISTIC_EXT, ObjectAddressSet, ObjectIdGetDatum(), OidIsValid, RelationGetDescr, ReleaseSysCache(), RowExclusiveLock, SearchSysCache1(), stmt, table_close(), table_open(), and WARNING.

Referenced by ProcessUtilitySlow().

◆ ChooseExtendedStatisticName()

static char * ChooseExtendedStatisticName ( const char name1,
const char name2,
const char label,
Oid  namespaceid 
)
static

Definition at line 879 of file statscmds.c.

881{
882 int pass = 0;
883 char *stxname = NULL;
884 char modlabel[NAMEDATALEN];
885
886 /* try the unmodified label first */
887 strlcpy(modlabel, label, sizeof(modlabel));
888
889 for (;;)
890 {
892
894
899 break;
900
901 /* found a conflict, so try a new name component */
902 pfree(stxname);
903 snprintf(modlabel, sizeof(modlabel), "%s%d", label, ++pass);
904 }
905
906 return stxname;
907}
char * makeObjectName(const char *name1, const char *name2, const char *label)
Definition indexcmds.c:2556
void pfree(void *pointer)
Definition mcxt.c:1619
static char * label
#define NAMEDATALEN
#define snprintf
Definition port.h:261
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition strlcpy.c:45
#define PointerGetDatum(X)
Definition postgres.h:354
#define GetSysCacheOid2(cacheId, oidcol, key1, key2)
Definition syscache.h:111

References fb(), GetSysCacheOid2, label, makeObjectName(), NAMEDATALEN, ObjectIdGetDatum(), OidIsValid, pfree(), PointerGetDatum, snprintf, and strlcpy().

Referenced by CreateStatistics().

◆ ChooseExtendedStatisticNameAddition()

static char * ChooseExtendedStatisticNameAddition ( List exprs)
static

Definition at line 921 of file statscmds.c.

922{
923 char buf[NAMEDATALEN * 2];
924 int buflen = 0;
925 ListCell *lc;
926
927 buf[0] = '\0';
928 foreach(lc, exprs)
929 {
931 const char *name;
932
933 /* It should be one of these, but just skip if it happens not to be */
934 if (!IsA(selem, StatsElem))
935 continue;
936
937 name = selem->name;
938
939 if (buflen > 0)
940 buf[buflen++] = '_'; /* insert _ between names */
941
942 /*
943 * We use fixed 'expr' for expressions, which have empty column names.
944 * For indexes this is handled in ChooseIndexColumnNames, but we have
945 * no such function for stats and it does not seem worth adding. If a
946 * better name is needed, the user can specify it explicitly.
947 */
948 if (!name)
949 name = "expr";
950
951 /*
952 * At this point we have buflen <= NAMEDATALEN. name should be less
953 * than NAMEDATALEN already, but use strlcpy for paranoia.
954 */
955 strlcpy(buf + buflen, name, NAMEDATALEN);
956 buflen += strlen(buf + buflen);
957 if (buflen >= NAMEDATALEN)
958 break;
959 }
960 return pstrdup(buf);
961}
char * pstrdup(const char *in)
Definition mcxt.c:1910
#define IsA(nodeptr, _type_)
Definition nodes.h:162
#define lfirst(lc)
Definition pg_list.h:172
static char buf[DEFAULT_XLOG_SEG_SIZE]
char * name
const char * name

References buf, fb(), IsA, lfirst, name, StatsElem::name, NAMEDATALEN, pstrdup(), and strlcpy().

Referenced by CreateStatistics().

◆ compare_int16()

static int compare_int16 ( const void a,
const void b 
)
static

Definition at line 51 of file statscmds.c.

52{
53 int av = *(const int16 *) a;
54 int bv = *(const int16 *) b;
55
56 /* this can't overflow if int is wider than int16 */
57 return (av - bv);
58}
int16_t int16
Definition c.h:678
int b
Definition isn.c:74
int a
Definition isn.c:73
struct @10::@11 av[32]

References a, av, b, and fb().

Referenced by CreateStatistics().

◆ CreateStatistics()

ObjectAddress CreateStatistics ( CreateStatsStmt stmt,
bool  check_rights 
)

Definition at line 64 of file statscmds.c.

65{
67 int nattnums = 0;
68 int numcols;
69 char *namestr;
74 HeapTuple htup;
76 bool nulls[Natts_pg_statistic_ext];
78 List *stxexprs = NIL;
81 Relation rel = NULL;
82 Oid relid;
84 myself;
85 Datum types[4]; /* one for each possible type of statistic */
86 int ntypes;
88 bool build_ndistinct;
90 bool build_mcv;
92 bool requested_type = false;
93 int i;
94 ListCell *cell;
96
98
99 /*
100 * Examine the FROM clause. Currently, we only allow it to be a single
101 * simple table, but later we'll probably allow multiple tables and JOIN
102 * syntax. The grammar is already prepared for that, so we have to check
103 * here that what we got is what we can support.
104 */
105 if (list_length(stmt->relations) != 1)
108 errmsg("only a single relation is allowed in CREATE STATISTICS")));
109
110 foreach(cell, stmt->relations)
111 {
112 Node *rln = (Node *) lfirst(cell);
113
114 if (!IsA(rln, RangeVar))
117 errmsg("only a single relation is allowed in CREATE STATISTICS")));
118
119 /*
120 * CREATE STATISTICS will influence future execution plans but does
121 * not interfere with currently executing plans. So it should be
122 * enough to take only ShareUpdateExclusiveLock on relation,
123 * conflicting with ANALYZE and other DDL that sets statistical
124 * information, but not with normal queries.
125 */
127
128 /* Restrict to allowed relation types */
129 if (rel->rd_rel->relkind != RELKIND_RELATION &&
130 rel->rd_rel->relkind != RELKIND_MATVIEW &&
131 rel->rd_rel->relkind != RELKIND_FOREIGN_TABLE &&
132 rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
135 errmsg("cannot define statistics for relation \"%s\"",
138
139 /*
140 * You must own the relation to create stats on it.
141 *
142 * NB: Concurrent changes could cause this function's lookup to find a
143 * different relation than a previous lookup by the caller, so we must
144 * perform this check even when check_rights == false.
145 */
149
150 /*
151 * Conflict log tables are system-managed tables used internally for
152 * logical replication conflict logging. Unlike user tables, they are
153 * not expected to have complex query usage, so to keep things simple,
154 * user-defined extended statistics are not required or supported at
155 * present.
156 */
160 errmsg("cannot create statistics on conflict log table \"%s\"",
162 errdetail("Conflict log tables are system-managed tables for logical replication conflicts.")));
163
164 /* Creating statistics on system catalogs is not allowed */
168 errmsg("permission denied: \"%s\" is a system catalog",
170 }
171
172 Assert(rel);
173 relid = RelationGetRelid(rel);
174
175 /*
176 * If the node has a name, split it up and determine creation namespace.
177 * If not, put the object in the same namespace as the relation, and cons
178 * up a name for it. (This can happen either via "CREATE STATISTICS ..."
179 * or via "CREATE TABLE ... (LIKE)".)
180 */
181 if (stmt->defnames)
183 &namestr);
184 else
185 {
189 "stat",
191 }
193
194 /*
195 * Check we have creation rights in target namespace. Skip check if
196 * caller doesn't want it.
197 */
198 if (check_rights)
199 {
201
204 if (aclresult != ACLCHECK_OK)
207 }
208
209 /*
210 * Deal with the possibility that the statistics object already exists.
211 */
215 {
216 if (stmt->if_not_exists)
217 {
218 /*
219 * Since stats objects aren't members of extensions (see comments
220 * below), no need for checkMembershipInCurrentExtension here.
221 */
224 errmsg("statistics object \"%s\" already exists, skipping",
225 namestr)));
228 }
229
232 errmsg("statistics object \"%s\" already exists", namestr)));
233 }
234
235 /*
236 * Make sure no more than STATS_MAX_DIMENSIONS columns are used. There
237 * might be duplicates and so on, but we'll deal with those later.
238 */
239 numcols = list_length(stmt->exprs);
243 errmsg("cannot have more than %d columns in statistics",
245
246 /*
247 * Convert the expression list to a simple array of attnums, but also keep
248 * a list of more complex expressions. While at it, enforce some
249 * constraints - we don't allow extended statistics on system attributes,
250 * and we require the data type to have a less-than operator, if we're
251 * building multivariate statistics.
252 *
253 * There are many ways to "mask" a simple attribute reference as an
254 * expression, for example "(a+0)" etc. We can't possibly detect all of
255 * them, but we handle at least the simple case with the attribute in
256 * parens. There'll always be a way around this, if the user is determined
257 * (like the "(a+0)" example), but this makes it somewhat consistent with
258 * how indexes treat attributes/expressions.
259 */
260 foreach(cell, stmt->exprs)
261 {
263
264 if (selem->name) /* column reference */
265 {
266 char *attname;
270
271 attname = selem->name;
272
277 errmsg("column \"%s\" does not exist",
278 attname)));
280
281 /* Disallow use of system attributes in extended stats */
282 if (attForm->attnum <= 0)
285 errmsg("statistics creation on system columns is not supported")));
286
287 /*
288 * Disallow data types without a less-than operator in
289 * multivariate statistics.
290 */
291 if (numcols > 1)
292 {
294 if (type->lt_opr == InvalidOid)
297 errmsg("cannot create multivariate statistics on column \"%s\"",
298 attname),
299 errdetail("The type %s has no default btree operator class.",
300 format_type_be(attForm->atttypid))));
301 }
302
303 /* Treat virtual generated columns as expressions */
304 if (attForm->attgenerated == ATTRIBUTE_GENERATED_VIRTUAL)
305 {
306 Node *expr;
307
308 expr = (Node *) makeVar(1,
309 attForm->attnum,
310 attForm->atttypid,
311 attForm->atttypmod,
312 attForm->attcollation,
313 0);
314 stxexprs = lappend(stxexprs, expr);
315 }
316 else
317 {
318 attnums[nattnums] = attForm->attnum;
319 nattnums++;
320 }
322 }
323 else if (IsA(selem->expr, Var)) /* column reference in parens */
324 {
325 Var *var = (Var *) selem->expr;
327
328 /* Disallow use of system attributes in extended stats */
329 if (var->varattno <= 0)
332 errmsg("statistics creation on system columns is not supported")));
333
334 /*
335 * Disallow data types without a less-than operator in
336 * multivariate statistics.
337 */
338 if (numcols > 1)
339 {
340 type = lookup_type_cache(var->vartype, TYPECACHE_LT_OPR);
341 if (type->lt_opr == InvalidOid)
344 errmsg("cannot create multivariate statistics on column \"%s\"",
345 get_attname(relid, var->varattno, false)),
346 errdetail("The type %s has no default btree operator class.",
347 format_type_be(var->vartype))));
348 }
349
350 /* Treat virtual generated columns as expressions */
351 if (get_attgenerated(relid, var->varattno) == ATTRIBUTE_GENERATED_VIRTUAL)
352 {
353 stxexprs = lappend(stxexprs, (Node *) var);
354 }
355 else
356 {
357 attnums[nattnums] = var->varattno;
358 nattnums++;
359 }
360 }
361 else /* expression */
362 {
363 Node *expr = selem->expr;
364 Oid atttype;
366 Bitmapset *attnums = NULL;
367 int k;
368
369 Assert(expr != NULL);
370
371 pull_varattnos(expr, 1, &attnums);
372
373 k = -1;
374 while ((k = bms_next_member(attnums, k)) >= 0)
375 {
377
378 /* Disallow expressions referencing system attributes. */
379 if (attnum <= 0)
382 errmsg("statistics creation on system columns is not supported")));
383 }
384
385 /*
386 * Disallow data types without a less-than operator in
387 * multivariate statistics.
388 */
389 if (numcols > 1)
390 {
391 atttype = exprType(expr);
393 if (type->lt_opr == InvalidOid)
396 errmsg("cannot create multivariate statistics on this expression"),
397 errdetail("The type %s has no default btree operator class.",
398 format_type_be(atttype))));
399 }
400
401 stxexprs = lappend(stxexprs, expr);
402 }
403 }
404
405 /*
406 * Check that at least two columns were specified in the statement, or
407 * that we're building statistics on a single expression (or virtual
408 * generated column).
409 */
410 if (numcols < 2 && list_length(stxexprs) != 1)
413 errmsg("cannot create extended statistics on a single non-virtual column"),
414 errdetail("Univariate statistics are already built for each individual non-virtual table column."));
415
416 /*
417 * Parse the statistics kinds (not allowed when building univariate
418 * statistics).
419 */
420 if (numcols == 1 && stmt->stat_types != NIL)
423 errmsg("cannot specify statistics kinds when building univariate statistics"));
424
425 build_ndistinct = false;
426 build_dependencies = false;
427 build_mcv = false;
428 foreach(cell, stmt->stat_types)
429 {
430 char *type = strVal(lfirst(cell));
431
432 if (strcmp(type, "ndistinct") == 0)
433 {
434 build_ndistinct = true;
435 requested_type = true;
436 }
437 else if (strcmp(type, "dependencies") == 0)
438 {
439 build_dependencies = true;
440 requested_type = true;
441 }
442 else if (strcmp(type, "mcv") == 0)
443 {
444 build_mcv = true;
445 requested_type = true;
446 }
447 else
450 errmsg("unrecognized statistics kind \"%s\"",
451 type)));
452 }
453
454 /*
455 * If no statistic type was specified, build them all (but only when the
456 * statistics is defined on more than one column/expression).
457 */
458 if ((!requested_type) && (numcols >= 2))
459 {
460 build_ndistinct = true;
461 build_dependencies = true;
462 build_mcv = true;
463 }
464
465 /*
466 * When there are non-trivial expressions, build the expression stats
467 * automatically. This allows calculating good estimates for stats that
468 * consider per-clause estimates (e.g. functional dependencies).
469 */
471
472 /*
473 * Sort the attnums, which makes detecting duplicates somewhat easier, and
474 * it does not hurt (it does not matter for the contents, unlike for
475 * indexes, for example).
476 */
477 qsort(attnums, nattnums, sizeof(int16), compare_int16);
478
479 /*
480 * Check for duplicates in the list of columns. The attnums are sorted so
481 * just check consecutive elements.
482 */
483 for (i = 1; i < nattnums; i++)
484 {
485 if (attnums[i] == attnums[i - 1])
488 errmsg("duplicate column name in statistics definition")));
489 }
490
491 /*
492 * Check for duplicate expressions. We do two loops, counting the
493 * occurrences of each expression. This is O(N^2) but we only allow small
494 * number of expressions and it's not executed often.
495 *
496 * XXX We don't cross-check attributes and expressions, because it does
497 * not seem worth it. In principle we could check that expressions don't
498 * contain trivial attribute references like "(a)", but the reasoning is
499 * similar to why we don't bother with extracting columns from
500 * expressions. It's either expensive or very easy to defeat for
501 * determined user, and there's no risk if we allow such statistics (the
502 * statistics is useless, but harmless).
503 */
504 foreach(cell, stxexprs)
505 {
506 Node *expr1 = (Node *) lfirst(cell);
507 int cnt = 0;
508
509 foreach(cell2, stxexprs)
510 {
511 Node *expr2 = (Node *) lfirst(cell2);
512
513 if (equal(expr1, expr2))
514 cnt += 1;
515 }
516
517 /* every expression should find at least itself */
518 Assert(cnt >= 1);
519
520 if (cnt > 1)
523 errmsg("duplicate expression in statistics definition")));
524 }
525
526 /* Form an int2vector representation of the sorted column list */
527 stxkeys = buildint2vector(attnums, nattnums);
528
529 /* construct the char array of enabled statistic types */
530 ntypes = 0;
531 if (build_ndistinct)
535 if (build_mcv)
539 Assert(ntypes > 0 && ntypes <= lengthof(types));
541
542 /* convert the expressions (if any) to a text datum */
543 if (stxexprs != NIL)
544 {
545 char *exprsString;
546
550 }
551 else
552 exprsDatum = (Datum) 0;
553
555
556 /*
557 * Everything seems fine, so let's build the pg_statistic_ext tuple.
558 */
559 memset(values, 0, sizeof(values));
560 memset(nulls, false, sizeof(nulls));
561
570 nulls[Anum_pg_statistic_ext_stxstattarget - 1] = true;
572
574 if (exprsDatum == (Datum) 0)
575 nulls[Anum_pg_statistic_ext_stxexprs - 1] = true;
576
577 /* insert it into pg_statistic_ext */
578 htup = heap_form_tuple(statrel->rd_att, values, nulls);
580 heap_freetuple(htup);
581
583
584 /*
585 * We used to create the pg_statistic_ext_data tuple too, but it's not
586 * clear what value should the stxdinherit flag have (it depends on
587 * whether the rel is partitioned, contains data, etc.)
588 */
589
591
592 /*
593 * Invalidate relcache so that others see the new statistics object.
594 */
596
598
599 /*
600 * Add an AUTO dependency on each column used in the stats, so that the
601 * stats object goes away if any or all of them get dropped.
602 */
604
605 /* add dependencies for plain column references */
606 for (i = 0; i < nattnums; i++)
607 {
610 }
611
612 /*
613 * If there are no dependencies on a column, give the statistics object an
614 * auto dependency on the whole table. In most cases, this will be
615 * redundant, but it might not be if the statistics expressions contain no
616 * Vars (which might seem strange but possible). This is consistent with
617 * what we do for indexes in index_create.
618 *
619 * XXX We intentionally don't consider the expressions before adding this
620 * dependency, because recordDependencyOnSingleRelExpr may not create any
621 * dependencies for whole-row Vars.
622 */
623 if (!nattnums)
624 {
627 }
628
629 /*
630 * Store dependencies on anything mentioned in statistics expressions,
631 * just like we do for index expressions.
632 */
633 if (stxexprs)
635 (Node *) stxexprs,
636 relid,
638 DEPENDENCY_AUTO, false);
639
640 /*
641 * Also add dependencies on namespace and owner. These are required
642 * because the stats object might have a different namespace and/or owner
643 * than the underlying table(s).
644 */
647
649
650 /*
651 * XXX probably there should be a recordDependencyOnCurrentExtension call
652 * here too, but we'd have to add support for ALTER EXTENSION ADD/DROP
653 * STATISTICS, which is more work than it seems worth.
654 */
655
656 /* Add any requested comment */
657 if (stmt->stxcomment != NULL)
659 stmt->stxcomment);
660
661 /* Return stats object's address */
662 return myself;
663}
AclResult
Definition acl.h:183
@ ACLCHECK_OK
Definition acl.h:184
AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
Definition aclchk.c:3902
ArrayType * construct_array_builtin(Datum *elems, int nelems, Oid elmtype)
int16 AttrNumber
Definition attnum.h:21
int bms_next_member(const Bitmapset *a, int prevbit)
Definition bitmapset.c:1290
static Datum values[MAXATTR]
Definition bootstrap.c:190
#define CStringGetTextDatum(s)
Definition builtins.h:98
#define lengthof(array)
Definition c.h:932
bool IsConflictLogTableClass(Form_pg_class reltuple)
Definition catalog.c:242
bool IsSystemRelation(Relation relation)
Definition catalog.c:74
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition catalog.c:475
void CreateComments(Oid oid, Oid classoid, int32 subid, const char *comment)
Definition comment.c:153
void recordDependencyOnSingleRelExpr(const ObjectAddress *depender, Node *expr, Oid relId, DependencyType behavior, DependencyType self_behavior, bool reverse_self)
@ DEPENDENCY_AUTO
Definition dependency.h:34
@ DEPENDENCY_NORMAL
Definition dependency.h:33
struct typedefs * types
Definition ecpg.c:30
int errdetail(const char *fmt,...) pg_attribute_printf(1
bool equal(const void *a, const void *b)
Definition equalfuncs.c:223
char * format_type_be(Oid type_oid)
bool allowSystemTableMods
Definition globals.c:132
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
Definition heaptuple.c:1025
static void * GETSTRUCT(const HeapTupleData *tuple)
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition indexing.c:233
int2vector * buildint2vector(const int16 *int2s, int n)
Definition int.c:114
void CacheInvalidateRelcache(Relation relation)
Definition inval.c:1632
int i
Definition isn.c:77
List * lappend(List *list, void *datum)
Definition list.c:339
#define NoLock
Definition lockdefs.h:34
#define ShareUpdateExclusiveLock
Definition lockdefs.h:39
char get_attgenerated(Oid relid, AttrNumber attnum)
Definition lsyscache.c:1114
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
Definition lsyscache.c:1053
char * get_namespace_name(Oid nspid)
Definition lsyscache.c:3682
Var * makeVar(int varno, AttrNumber varattno, Oid vartype, int32 vartypmod, Oid varcollid, Index varlevelsup)
Definition makefuncs.c:66
void namestrcpy(Name name, const char *str)
Definition name.c:233
Oid QualifiedNameGetCreationNamespace(const List *names, char **objname_p)
Definition namespace.c:3559
Oid exprType(const Node *expr)
Definition nodeFuncs.c:42
#define InvokeObjectPostCreateHook(classId, objectId, subId)
ObjectType get_relkind_objtype(char relkind)
#define ObjectAddressSubSet(addr, class_id, object_id, object_sub_id)
char * nodeToString(const void *obj)
Definition outfuncs.c:811
@ OBJECT_SCHEMA
#define ACL_CREATE
Definition parsenodes.h:85
NameData attname
int16 attnum
FormData_pg_attribute * Form_pg_attribute
int errdetail_relkind_not_supported(char relkind)
Definition pg_class.c:24
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition pg_depend.c:51
#define lfirst_node(type, lc)
Definition pg_list.h:176
static int list_length(const List *l)
Definition pg_list.h:152
#define NIL
Definition pg_list.h:68
void recordDependencyOnOwner(Oid classId, Oid objectId, Oid owner)
#define qsort(a, b, c, d)
Definition port.h:496
static Datum NameGetDatum(const NameData *X)
Definition postgres.h:406
static Datum CStringGetDatum(const char *X)
Definition postgres.h:383
static Datum CharGetDatum(char X)
Definition postgres.h:132
#define InvalidOid
#define RelationGetRelid(relation)
Definition rel.h:516
#define RelationGetRelationName(relation)
Definition rel.h:550
#define RelationGetNamespace(relation)
Definition rel.h:557
void relation_close(Relation relation, LOCKMODE lockmode)
Definition relation.c:206
Relation relation_openrv(const RangeVar *relation, LOCKMODE lockmode)
Definition relation.c:138
#define STATS_MAX_DIMENSIONS
Definition statistics.h:19
static char * ChooseExtendedStatisticNameAddition(List *exprs)
Definition statscmds.c:921
static char * ChooseExtendedStatisticName(const char *name1, const char *name2, const char *label, Oid namespaceid)
Definition statscmds.c:879
static int compare_int16(const void *a, const void *b)
Definition statscmds.c:51
#define ERRCODE_DUPLICATE_OBJECT
Definition streamutil.c:30
Definition pg_list.h:54
Definition nodes.h:133
Form_pg_class rd_rel
Definition rel.h:111
Definition c.h:889
#define FirstLowInvalidHeapAttributeNumber
Definition sysattr.h:27
HeapTuple SearchSysCacheAttName(Oid relid, const char *attname)
Definition syscache.c:476
#define SearchSysCacheExists2(cacheId, key1, key2)
Definition syscache.h:102
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition typcache.c:389
#define TYPECACHE_LT_OPR
Definition typcache.h:139
#define strVal(v)
Definition value.h:82
void pull_varattnos(Node *node, Index varno, Bitmapset **varattnos)
Definition var.c:296
const char * type

References ACL_CREATE, aclcheck_error(), ACLCHECK_NOT_OWNER, ACLCHECK_OK, allowSystemTableMods, Assert, attname, attnum, bms_next_member(), buildint2vector(), CacheInvalidateRelcache(), CatalogTupleInsert(), CharGetDatum(), ChooseExtendedStatisticName(), ChooseExtendedStatisticNameAddition(), compare_int16(), construct_array_builtin(), CreateComments(), CStringGetDatum(), CStringGetTextDatum, DEPENDENCY_AUTO, DEPENDENCY_NORMAL, equal(), ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errdetail(), errdetail_relkind_not_supported(), errmsg, ERROR, exprType(), fb(), FirstLowInvalidHeapAttributeNumber, format_type_be(), get_attgenerated(), get_attname(), get_namespace_name(), get_relkind_objtype(), GetNewOidWithIndex(), GETSTRUCT(), GetUserId(), heap_form_tuple(), heap_freetuple(), HeapTupleIsValid, i, InvalidObjectAddress, InvalidOid, InvokeObjectPostCreateHook, IsA, IsConflictLogTableClass(), IsSystemRelation(), lappend(), lengthof, lfirst, lfirst_node, list_length(), lookup_type_cache(), makeVar(), NameGetDatum(), namestrcpy(), NIL, nodeToString(), NoLock, NOTICE, object_aclcheck(), object_ownercheck(), OBJECT_SCHEMA, ObjectAddressSet, ObjectAddressSubSet, ObjectIdGetDatum(), pfree(), PointerGetDatum, pull_varattnos(), qsort, QualifiedNameGetCreationNamespace(), RelationData::rd_rel, recordDependencyOn(), recordDependencyOnOwner(), recordDependencyOnSingleRelExpr(), relation_close(), relation_openrv(), RelationGetNamespace, RelationGetRelationName, RelationGetRelid, ReleaseSysCache(), RowExclusiveLock, SearchSysCacheAttName(), SearchSysCacheExists2, ShareUpdateExclusiveLock, STATS_MAX_DIMENSIONS, stmt, strVal, table_open(), type, TYPECACHE_LT_OPR, types, values, and Var::varattno.

Referenced by ATExecAddStatistics(), and ProcessUtilitySlow().

◆ RemoveStatisticsById()

void RemoveStatisticsById ( Oid  statsOid)

Definition at line 817 of file statscmds.c.

818{
819 Relation relation;
820 Relation rel;
823 Oid relid;
824
825 /*
826 * Delete the pg_statistic_ext tuple. Also send out a cache inval on the
827 * associated table, so that dependent plans will be rebuilt.
828 */
830
832
833 if (!HeapTupleIsValid(tup)) /* should not happen */
834 elog(ERROR, "cache lookup failed for statistics object %u", statsOid);
835
837 relid = statext->stxrelid;
838
839 /*
840 * Delete the pg_statistic_ext_data tuples holding the actual statistical
841 * data. There might be data with/without inheritance, so attempt deleting
842 * both. We lock the user table first, to prevent other processes (e.g.
843 * DROP STATISTICS) from removing the row concurrently.
844 */
846
849
851
852 CatalogTupleDelete(relation, &tup->t_self);
853
855
856 /* Keep lock until the end of the transaction. */
857 table_close(rel, NoLock);
858
859 table_close(relation, RowExclusiveLock);
860}
void CatalogTupleDelete(Relation heapRel, const ItemPointerData *tid)
Definition indexing.c:365
void CacheInvalidateRelcacheByRelid(Oid relid)
Definition inval.c:1688
END_CATALOG_STRUCT typedef FormData_pg_statistic_ext * Form_pg_statistic_ext
void RemoveStatisticsDataById(Oid statsOid, bool inh)
Definition statscmds.c:792

References CacheInvalidateRelcacheByRelid(), CatalogTupleDelete(), elog, ERROR, fb(), Form_pg_statistic_ext, GETSTRUCT(), HeapTupleIsValid, NoLock, ObjectIdGetDatum(), ReleaseSysCache(), RemoveStatisticsDataById(), RowExclusiveLock, SearchSysCache1(), ShareUpdateExclusiveLock, table_close(), and table_open().

Referenced by doDeletion().

◆ RemoveStatisticsDataById()

void RemoveStatisticsDataById ( Oid  statsOid,
bool  inh 
)

Definition at line 792 of file statscmds.c.

793{
794 Relation relation;
796
798
800 BoolGetDatum(inh));
801
802 /* We don't know if the data row for inh value exists. */
804 {
805 CatalogTupleDelete(relation, &tup->t_self);
806
808 }
809
810 table_close(relation, RowExclusiveLock);
811}
static Datum BoolGetDatum(bool X)
Definition postgres.h:112
HeapTuple SearchSysCache2(SysCacheIdentifier cacheId, Datum key1, Datum key2)
Definition syscache.c:231

References BoolGetDatum(), CatalogTupleDelete(), fb(), HeapTupleIsValid, ObjectIdGetDatum(), ReleaseSysCache(), RowExclusiveLock, SearchSysCache2(), table_close(), and table_open().

Referenced by RemoveStatisticsById(), and statext_store().

◆ StatisticsGetRelation()

Oid StatisticsGetRelation ( Oid  statId,
bool  missing_ok 
)

Definition at line 968 of file statscmds.c.

969{
970 HeapTuple tuple;
972 Oid result;
973
975 if (!HeapTupleIsValid(tuple))
976 {
977 if (missing_ok)
978 return InvalidOid;
979 elog(ERROR, "cache lookup failed for statistics object %u", statId);
980 }
982 Assert(stx->oid == statId);
983
984 result = stx->stxrelid;
985 ReleaseSysCache(tuple);
986 return result;
987}
uint32 result

References Assert, elog, ERROR, fb(), Form_pg_statistic_ext, GETSTRUCT(), HeapTupleIsValid, InvalidOid, ObjectIdGetDatum(), ReleaseSysCache(), result, and SearchSysCache1().

Referenced by ATPostAlterTypeCleanup().