PostgreSQL Source Code git master
Loading...
Searching...
No Matches
statscmds.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * statscmds.c
4 * Commands for creating and altering extended statistics objects
5 *
6 * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
8 *
9 *
10 * IDENTIFICATION
11 * src/backend/commands/statscmds.c
12 *
13 *-------------------------------------------------------------------------
14 */
15#include "postgres.h"
16
17#include "access/htup_details.h"
18#include "access/relation.h"
19#include "access/table.h"
20#include "catalog/catalog.h"
21#include "catalog/dependency.h"
22#include "catalog/indexing.h"
23#include "catalog/namespace.h"
28#include "commands/comment.h"
29#include "commands/defrem.h"
30#include "miscadmin.h"
31#include "nodes/makefuncs.h"
32#include "nodes/nodeFuncs.h"
33#include "optimizer/optimizer.h"
35#include "utils/acl.h"
36#include "utils/builtins.h"
37#include "utils/inval.h"
38#include "utils/lsyscache.h"
39#include "utils/rel.h"
40#include "utils/syscache.h"
41#include "utils/typcache.h"
42
43
44static char *ChooseExtendedStatisticName(const char *name1, const char *name2,
45 const char *label, Oid namespaceid);
46static char *ChooseExtendedStatisticNameAddition(List *exprs);
47
48
49/* qsort comparator for the attnums in CreateStatistics */
50static int
51compare_int16(const void *a, const void *b)
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}
59
60/*
61 * CREATE STATISTICS
62 */
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 /* Creating statistics on system catalogs is not allowed */
154 errmsg("permission denied: \"%s\" is a system catalog",
156 }
157
158 Assert(rel);
159 relid = RelationGetRelid(rel);
160
161 /*
162 * If the node has a name, split it up and determine creation namespace.
163 * If not, put the object in the same namespace as the relation, and cons
164 * up a name for it. (This can happen either via "CREATE STATISTICS ..."
165 * or via "CREATE TABLE ... (LIKE)".)
166 */
167 if (stmt->defnames)
169 &namestr);
170 else
171 {
175 "stat",
177 }
179
180 /*
181 * Check we have creation rights in target namespace. Skip check if
182 * caller doesn't want it.
183 */
184 if (check_rights)
185 {
187
190 if (aclresult != ACLCHECK_OK)
193 }
194
195 /*
196 * Deal with the possibility that the statistics object already exists.
197 */
201 {
202 if (stmt->if_not_exists)
203 {
204 /*
205 * Since stats objects aren't members of extensions (see comments
206 * below), no need for checkMembershipInCurrentExtension here.
207 */
210 errmsg("statistics object \"%s\" already exists, skipping",
211 namestr)));
214 }
215
218 errmsg("statistics object \"%s\" already exists", namestr)));
219 }
220
221 /*
222 * Make sure no more than STATS_MAX_DIMENSIONS columns are used. There
223 * might be duplicates and so on, but we'll deal with those later.
224 */
225 numcols = list_length(stmt->exprs);
229 errmsg("cannot have more than %d columns in statistics",
231
232 /*
233 * Convert the expression list to a simple array of attnums, but also keep
234 * a list of more complex expressions. While at it, enforce some
235 * constraints - we don't allow extended statistics on system attributes,
236 * and we require the data type to have a less-than operator, if we're
237 * building multivariate statistics.
238 *
239 * There are many ways to "mask" a simple attribute reference as an
240 * expression, for example "(a+0)" etc. We can't possibly detect all of
241 * them, but we handle at least the simple case with the attribute in
242 * parens. There'll always be a way around this, if the user is determined
243 * (like the "(a+0)" example), but this makes it somewhat consistent with
244 * how indexes treat attributes/expressions.
245 */
246 foreach(cell, stmt->exprs)
247 {
249
250 if (selem->name) /* column reference */
251 {
252 char *attname;
256
257 attname = selem->name;
258
263 errmsg("column \"%s\" does not exist",
264 attname)));
266
267 /* Disallow use of system attributes in extended stats */
268 if (attForm->attnum <= 0)
271 errmsg("statistics creation on system columns is not supported")));
272
273 /*
274 * Disallow data types without a less-than operator in
275 * multivariate statistics.
276 */
277 if (numcols > 1)
278 {
280 if (type->lt_opr == InvalidOid)
283 errmsg("cannot create multivariate statistics on column \"%s\"",
284 attname),
285 errdetail("The type %s has no default btree operator class.",
286 format_type_be(attForm->atttypid))));
287 }
288
289 /* Treat virtual generated columns as expressions */
290 if (attForm->attgenerated == ATTRIBUTE_GENERATED_VIRTUAL)
291 {
292 Node *expr;
293
294 expr = (Node *) makeVar(1,
295 attForm->attnum,
296 attForm->atttypid,
297 attForm->atttypmod,
298 attForm->attcollation,
299 0);
300 stxexprs = lappend(stxexprs, expr);
301 }
302 else
303 {
304 attnums[nattnums] = attForm->attnum;
305 nattnums++;
306 }
308 }
309 else if (IsA(selem->expr, Var)) /* column reference in parens */
310 {
311 Var *var = (Var *) selem->expr;
313
314 /* Disallow use of system attributes in extended stats */
315 if (var->varattno <= 0)
318 errmsg("statistics creation on system columns is not supported")));
319
320 /*
321 * Disallow data types without a less-than operator in
322 * multivariate statistics.
323 */
324 if (numcols > 1)
325 {
326 type = lookup_type_cache(var->vartype, TYPECACHE_LT_OPR);
327 if (type->lt_opr == InvalidOid)
330 errmsg("cannot create multivariate statistics on column \"%s\"",
331 get_attname(relid, var->varattno, false)),
332 errdetail("The type %s has no default btree operator class.",
333 format_type_be(var->vartype))));
334 }
335
336 /* Treat virtual generated columns as expressions */
338 {
339 stxexprs = lappend(stxexprs, (Node *) var);
340 }
341 else
342 {
343 attnums[nattnums] = var->varattno;
344 nattnums++;
345 }
346 }
347 else /* expression */
348 {
349 Node *expr = selem->expr;
350 Oid atttype;
352 Bitmapset *attnums = NULL;
353 int k;
354
355 Assert(expr != NULL);
356
357 pull_varattnos(expr, 1, &attnums);
358
359 k = -1;
360 while ((k = bms_next_member(attnums, k)) >= 0)
361 {
363
364 /* Disallow expressions referencing system attributes. */
365 if (attnum <= 0)
368 errmsg("statistics creation on system columns is not supported")));
369 }
370
371 /*
372 * Disallow data types without a less-than operator in
373 * multivariate statistics.
374 */
375 if (numcols > 1)
376 {
377 atttype = exprType(expr);
379 if (type->lt_opr == InvalidOid)
382 errmsg("cannot create multivariate statistics on this expression"),
383 errdetail("The type %s has no default btree operator class.",
384 format_type_be(atttype))));
385 }
386
387 stxexprs = lappend(stxexprs, expr);
388 }
389 }
390
391 /*
392 * Check that at least two columns were specified in the statement, or
393 * that we're building statistics on a single expression (or virtual
394 * generated column).
395 */
396 if (numcols < 2 && list_length(stxexprs) != 1)
399 errmsg("cannot create extended statistics on a single non-virtual column"),
400 errdetail("Univariate statistics are already built for each individual non-virtual table column."));
401
402 /*
403 * Parse the statistics kinds (not allowed when building univariate
404 * statistics).
405 */
406 if (numcols == 1 && stmt->stat_types != NIL)
409 errmsg("cannot specify statistics kinds when building univariate statistics"));
410
411 build_ndistinct = false;
412 build_dependencies = false;
413 build_mcv = false;
414 foreach(cell, stmt->stat_types)
415 {
416 char *type = strVal(lfirst(cell));
417
418 if (strcmp(type, "ndistinct") == 0)
419 {
420 build_ndistinct = true;
421 requested_type = true;
422 }
423 else if (strcmp(type, "dependencies") == 0)
424 {
425 build_dependencies = true;
426 requested_type = true;
427 }
428 else if (strcmp(type, "mcv") == 0)
429 {
430 build_mcv = true;
431 requested_type = true;
432 }
433 else
436 errmsg("unrecognized statistics kind \"%s\"",
437 type)));
438 }
439
440 /*
441 * If no statistic type was specified, build them all (but only when the
442 * statistics is defined on more than one column/expression).
443 */
444 if ((!requested_type) && (numcols >= 2))
445 {
446 build_ndistinct = true;
447 build_dependencies = true;
448 build_mcv = true;
449 }
450
451 /*
452 * When there are non-trivial expressions, build the expression stats
453 * automatically. This allows calculating good estimates for stats that
454 * consider per-clause estimates (e.g. functional dependencies).
455 */
457
458 /*
459 * Sort the attnums, which makes detecting duplicates somewhat easier, and
460 * it does not hurt (it does not matter for the contents, unlike for
461 * indexes, for example).
462 */
463 qsort(attnums, nattnums, sizeof(int16), compare_int16);
464
465 /*
466 * Check for duplicates in the list of columns. The attnums are sorted so
467 * just check consecutive elements.
468 */
469 for (i = 1; i < nattnums; i++)
470 {
471 if (attnums[i] == attnums[i - 1])
474 errmsg("duplicate column name in statistics definition")));
475 }
476
477 /*
478 * Check for duplicate expressions. We do two loops, counting the
479 * occurrences of each expression. This is O(N^2) but we only allow small
480 * number of expressions and it's not executed often.
481 *
482 * XXX We don't cross-check attributes and expressions, because it does
483 * not seem worth it. In principle we could check that expressions don't
484 * contain trivial attribute references like "(a)", but the reasoning is
485 * similar to why we don't bother with extracting columns from
486 * expressions. It's either expensive or very easy to defeat for
487 * determined user, and there's no risk if we allow such statistics (the
488 * statistics is useless, but harmless).
489 */
490 foreach(cell, stxexprs)
491 {
492 Node *expr1 = (Node *) lfirst(cell);
493 int cnt = 0;
494
495 foreach(cell2, stxexprs)
496 {
497 Node *expr2 = (Node *) lfirst(cell2);
498
499 if (equal(expr1, expr2))
500 cnt += 1;
501 }
502
503 /* every expression should find at least itself */
504 Assert(cnt >= 1);
505
506 if (cnt > 1)
509 errmsg("duplicate expression in statistics definition")));
510 }
511
512 /* Form an int2vector representation of the sorted column list */
513 stxkeys = buildint2vector(attnums, nattnums);
514
515 /* construct the char array of enabled statistic types */
516 ntypes = 0;
517 if (build_ndistinct)
521 if (build_mcv)
525 Assert(ntypes > 0 && ntypes <= lengthof(types));
527
528 /* convert the expressions (if any) to a text datum */
529 if (stxexprs != NIL)
530 {
531 char *exprsString;
532
536 }
537 else
538 exprsDatum = (Datum) 0;
539
541
542 /*
543 * Everything seems fine, so let's build the pg_statistic_ext tuple.
544 */
545 memset(values, 0, sizeof(values));
546 memset(nulls, false, sizeof(nulls));
547
556 nulls[Anum_pg_statistic_ext_stxstattarget - 1] = true;
558
560 if (exprsDatum == (Datum) 0)
561 nulls[Anum_pg_statistic_ext_stxexprs - 1] = true;
562
563 /* insert it into pg_statistic_ext */
564 htup = heap_form_tuple(statrel->rd_att, values, nulls);
566 heap_freetuple(htup);
567
569
570 /*
571 * We used to create the pg_statistic_ext_data tuple too, but it's not
572 * clear what value should the stxdinherit flag have (it depends on
573 * whether the rel is partitioned, contains data, etc.)
574 */
575
577
578 /*
579 * Invalidate relcache so that others see the new statistics object.
580 */
582
584
585 /*
586 * Add an AUTO dependency on each column used in the stats, so that the
587 * stats object goes away if any or all of them get dropped.
588 */
590
591 /* add dependencies for plain column references */
592 for (i = 0; i < nattnums; i++)
593 {
596 }
597
598 /*
599 * If there are no dependencies on a column, give the statistics object an
600 * auto dependency on the whole table. In most cases, this will be
601 * redundant, but it might not be if the statistics expressions contain no
602 * Vars (which might seem strange but possible). This is consistent with
603 * what we do for indexes in index_create.
604 *
605 * XXX We intentionally don't consider the expressions before adding this
606 * dependency, because recordDependencyOnSingleRelExpr may not create any
607 * dependencies for whole-row Vars.
608 */
609 if (!nattnums)
610 {
613 }
614
615 /*
616 * Store dependencies on anything mentioned in statistics expressions,
617 * just like we do for index expressions.
618 */
619 if (stxexprs)
621 (Node *) stxexprs,
622 relid,
624 DEPENDENCY_AUTO, false);
625
626 /*
627 * Also add dependencies on namespace and owner. These are required
628 * because the stats object might have a different namespace and/or owner
629 * than the underlying table(s).
630 */
633
635
636 /*
637 * XXX probably there should be a recordDependencyOnCurrentExtension call
638 * here too, but we'd have to add support for ALTER EXTENSION ADD/DROP
639 * STATISTICS, which is more work than it seems worth.
640 */
641
642 /* Add any requested comment */
643 if (stmt->stxcomment != NULL)
645 stmt->stxcomment);
646
647 /* Return stats object's address */
648 return myself;
649}
650
651/*
652 * ALTER STATISTICS
653 */
656{
657 Relation rel;
658 Oid stxoid;
664 ObjectAddress address;
665 int newtarget = 0;
667
668 /* -1 was used in previous versions for the default setting */
669 if (stmt->stxstattarget && intVal(stmt->stxstattarget) != -1)
670 {
671 newtarget = intVal(stmt->stxstattarget);
672 newtarget_default = false;
673 }
674 else
675 newtarget_default = true;
676
678 {
679 /* Limit statistics target to a sane range */
680 if (newtarget < 0)
681 {
684 errmsg("statistics target %d is too low",
685 newtarget)));
686 }
688 {
692 errmsg("lowering statistics target to %d",
693 newtarget)));
694 }
695 }
696
697 /* lookup OID of the statistics object */
698 stxoid = get_statistics_object_oid(stmt->defnames, stmt->missing_ok);
699
700 /*
701 * If we got here and the OID is not valid, it means the statistics object
702 * does not exist, but the command specified IF EXISTS. So report this as
703 * a simple NOTICE and we're done.
704 */
705 if (!OidIsValid(stxoid))
706 {
707 char *schemaname;
708 char *statname;
709
710 Assert(stmt->missing_ok);
711
712 DeconstructQualifiedName(stmt->defnames, &schemaname, &statname);
713
714 if (schemaname)
716 (errmsg("statistics object \"%s.%s\" does not exist, skipping",
717 schemaname, statname)));
718 else
720 (errmsg("statistics object \"%s\" does not exist, skipping",
721 statname)));
722
724 }
725
726 /* Search pg_statistic_ext */
728
731 elog(ERROR, "cache lookup failed for extended statistics object %u", stxoid);
732
733 /* Must be owner of the existing statistics object */
736 NameListToString(stmt->defnames));
737
738 /* Build new tuple. */
739 memset(repl_val, 0, sizeof(repl_val));
740 memset(repl_null, false, sizeof(repl_null));
741 memset(repl_repl, false, sizeof(repl_repl));
742
743 /* replace the stxstattarget column */
747 else
749
752
753 /* Update system catalog. */
754 CatalogTupleUpdate(rel, &newtup->t_self, newtup);
755
757
759
760 /*
761 * NOTE: because we only support altering the statistics target, not the
762 * other fields, there is no need to update dependencies.
763 */
764
767
769
770 return address;
771}
772
773/*
774 * Delete entry in pg_statistic_ext_data catalog. We don't know if the row
775 * exists, so don't error out.
776 */
777void
779{
780 Relation relation;
782
784
786 BoolGetDatum(inh));
787
788 /* We don't know if the data row for inh value exists. */
790 {
791 CatalogTupleDelete(relation, &tup->t_self);
792
794 }
795
796 table_close(relation, RowExclusiveLock);
797}
798
799/*
800 * Guts of statistics object deletion.
801 */
802void
804{
805 Relation relation;
806 Relation rel;
809 Oid relid;
810
811 /*
812 * Delete the pg_statistic_ext tuple. Also send out a cache inval on the
813 * associated table, so that dependent plans will be rebuilt.
814 */
816
818
819 if (!HeapTupleIsValid(tup)) /* should not happen */
820 elog(ERROR, "cache lookup failed for statistics object %u", statsOid);
821
823 relid = statext->stxrelid;
824
825 /*
826 * Delete the pg_statistic_ext_data tuples holding the actual statistical
827 * data. There might be data with/without inheritance, so attempt deleting
828 * both. We lock the user table first, to prevent other processes (e.g.
829 * DROP STATISTICS) from removing the row concurrently.
830 */
832
835
837
838 CatalogTupleDelete(relation, &tup->t_self);
839
841
842 /* Keep lock until the end of the transaction. */
843 table_close(rel, NoLock);
844
845 table_close(relation, RowExclusiveLock);
846}
847
848/*
849 * Select a nonconflicting name for a new statistics object.
850 *
851 * name1, name2, and label are used the same way as for makeObjectName(),
852 * except that the label can't be NULL; digits will be appended to the label
853 * if needed to create a name that is unique within the specified namespace.
854 *
855 * Returns a palloc'd string.
856 *
857 * Note: it is theoretically possible to get a collision anyway, if someone
858 * else chooses the same name concurrently. This is fairly unlikely to be
859 * a problem in practice, especially if one is holding a share update
860 * exclusive lock on the relation identified by name1. However, if choosing
861 * multiple names within a single command, you'd better create the new object
862 * and do CommandCounterIncrement before choosing the next one!
863 */
864static char *
865ChooseExtendedStatisticName(const char *name1, const char *name2,
866 const char *label, Oid namespaceid)
867{
868 int pass = 0;
869 char *stxname = NULL;
870 char modlabel[NAMEDATALEN];
871
872 /* try the unmodified label first */
873 strlcpy(modlabel, label, sizeof(modlabel));
874
875 for (;;)
876 {
878
880
885 break;
886
887 /* found a conflict, so try a new name component */
888 pfree(stxname);
889 snprintf(modlabel, sizeof(modlabel), "%s%d", label, ++pass);
890 }
891
892 return stxname;
893}
894
895/*
896 * Generate "name2" for a new statistics object given the list of column
897 * names for it. This will be passed to ChooseExtendedStatisticName along
898 * with the parent table name and a suitable label.
899 *
900 * We know that less than NAMEDATALEN characters will actually be used,
901 * so we can truncate the result once we've generated that many.
902 *
903 * XXX see also ChooseForeignKeyConstraintNameAddition and
904 * ChooseIndexNameAddition.
905 */
906static char *
908{
909 char buf[NAMEDATALEN * 2];
910 int buflen = 0;
911 ListCell *lc;
912
913 buf[0] = '\0';
914 foreach(lc, exprs)
915 {
917 const char *name;
918
919 /* It should be one of these, but just skip if it happens not to be */
920 if (!IsA(selem, StatsElem))
921 continue;
922
923 name = selem->name;
924
925 if (buflen > 0)
926 buf[buflen++] = '_'; /* insert _ between names */
927
928 /*
929 * We use fixed 'expr' for expressions, which have empty column names.
930 * For indexes this is handled in ChooseIndexColumnNames, but we have
931 * no such function for stats and it does not seem worth adding. If a
932 * better name is needed, the user can specify it explicitly.
933 */
934 if (!name)
935 name = "expr";
936
937 /*
938 * At this point we have buflen <= NAMEDATALEN. name should be less
939 * than NAMEDATALEN already, but use strlcpy for paranoia.
940 */
941 strlcpy(buf + buflen, name, NAMEDATALEN);
942 buflen += strlen(buf + buflen);
943 if (buflen >= NAMEDATALEN)
944 break;
945 }
946 return pstrdup(buf);
947}
948
949/*
950 * StatisticsGetRelation: given a statistics object's OID, get the OID of
951 * the relation it is defined on. Uses the system cache.
952 */
953Oid
955{
956 HeapTuple tuple;
958 Oid result;
959
961 if (!HeapTupleIsValid(tuple))
962 {
963 if (missing_ok)
964 return InvalidOid;
965 elog(ERROR, "cache lookup failed for statistics object %u", statId);
966 }
968 Assert(stx->oid == statId);
969
970 result = stx->stxrelid;
971 ReleaseSysCache(tuple);
972 return result;
973}
AclResult
Definition acl.h:183
@ ACLCHECK_OK
Definition acl.h:184
@ ACLCHECK_NOT_OWNER
Definition acl.h:186
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition aclchk.c:2672
AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
Definition aclchk.c:3879
bool object_ownercheck(Oid classid, Oid objectid, Oid roleid)
Definition aclchk.c:4133
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 Assert(condition)
Definition c.h:943
int16_t int16
Definition c.h:619
#define lengthof(array)
Definition c.h:873
#define OidIsValid(objectId)
Definition c.h:858
bool IsSystemRelation(Relation relation)
Definition catalog.c:74
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition catalog.c:448
uint32 result
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 errcode(int sqlerrcode)
Definition elog.c:874
int errdetail(const char *fmt,...) pg_attribute_printf(1
#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
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_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, const Datum *replValues, const bool *replIsnull, const bool *doReplace)
Definition heaptuple.c:1118
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
Definition heaptuple.c:1025
void heap_freetuple(HeapTuple htup)
Definition heaptuple.c:1372
#define HeapTupleIsValid(tuple)
Definition htup.h:78
static void * GETSTRUCT(const HeapTupleData *tuple)
#define stmt
char * makeObjectName(const char *name1, const char *name2, const char *label)
Definition indexcmds.c:2546
void CatalogTupleUpdate(Relation heapRel, const ItemPointerData *otid, HeapTuple tup)
Definition indexing.c:313
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition indexing.c:233
void CatalogTupleDelete(Relation heapRel, const ItemPointerData *tid)
Definition indexing.c:365
int2vector * buildint2vector(const int16 *int2s, int n)
Definition int.c:114
void CacheInvalidateRelcache(Relation relation)
Definition inval.c:1635
void CacheInvalidateRelcacheByRelid(Oid relid)
Definition inval.c:1691
int b
Definition isn.c:74
int a
Definition isn.c:73
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
#define RowExclusiveLock
Definition lockdefs.h:38
char get_attgenerated(Oid relid, AttrNumber attnum)
Definition lsyscache.c:1007
char * get_attname(Oid relid, AttrNumber attnum, bool missing_ok)
Definition lsyscache.c:946
char * get_namespace_name(Oid nspid)
Definition lsyscache.c:3588
Var * makeVar(int varno, AttrNumber varattno, Oid vartype, int32 vartypmod, Oid varcollid, Index varlevelsup)
Definition makefuncs.c:66
char * pstrdup(const char *in)
Definition mcxt.c:1781
void pfree(void *pointer)
Definition mcxt.c:1616
Oid GetUserId(void)
Definition miscinit.c:470
void namestrcpy(Name name, const char *str)
Definition name.c:233
char * NameListToString(const List *names)
Definition namespace.c:3666
Oid QualifiedNameGetCreationNamespace(const List *names, char **objname_p)
Definition namespace.c:3559
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
Oid exprType(const Node *expr)
Definition nodeFuncs.c:42
#define IsA(nodeptr, _type_)
Definition nodes.h:164
static char * errmsg
#define InvokeObjectPostCreateHook(classId, objectId, subId)
#define InvokeObjectPostAlterHook(classId, objectId, subId)
ObjectType get_relkind_objtype(char relkind)
const ObjectAddress InvalidObjectAddress
#define ObjectAddressSet(addr, class_id, object_id)
#define ObjectAddressSubSet(addr, class_id, object_id, object_sub_id)
char * nodeToString(const void *obj)
Definition outfuncs.c:811
@ OBJECT_SCHEMA
@ OBJECT_STATISTIC_EXT
#define ACL_CREATE
Definition parsenodes.h:85
NameData attname
int16 attnum
FormData_pg_attribute * Form_pg_attribute
static char * label
int errdetail_relkind_not_supported(char relkind)
Definition pg_class.c:24
#define NAMEDATALEN
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition pg_depend.c:47
#define lfirst(lc)
Definition pg_list.h:172
#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)
END_CATALOG_STRUCT typedef FormData_pg_statistic_ext * Form_pg_statistic_ext
static char buf[DEFAULT_XLOG_SEG_SIZE]
#define snprintf
Definition port.h:260
#define qsort(a, b, c, d)
Definition port.h:495
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition strlcpy.c:45
static Datum PointerGetDatum(const void *X)
Definition postgres.h:342
static Datum Int16GetDatum(int16 X)
Definition postgres.h:172
static Datum BoolGetDatum(bool X)
Definition postgres.h:112
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:252
static Datum NameGetDatum(const NameData *X)
Definition postgres.h:393
uint64_t Datum
Definition postgres.h:70
static Datum CStringGetDatum(const char *X)
Definition postgres.h:370
static Datum CharGetDatum(char X)
Definition postgres.h:132
#define InvalidOid
unsigned int Oid
static int fb(int x)
#define RelationGetRelid(relation)
Definition rel.h:516
#define RelationGetDescr(relation)
Definition rel.h:542
#define RelationGetRelationName(relation)
Definition rel.h:550
#define RelationGetNamespace(relation)
Definition rel.h:557
struct @10::@11 av[32]
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
ObjectAddress CreateStatistics(CreateStatsStmt *stmt, bool check_rights)
Definition statscmds.c:64
ObjectAddress AlterStatistics(AlterStatsStmt *stmt)
Definition statscmds.c:655
static char * ChooseExtendedStatisticNameAddition(List *exprs)
Definition statscmds.c:907
void RemoveStatisticsDataById(Oid statsOid, bool inh)
Definition statscmds.c:778
static char * ChooseExtendedStatisticName(const char *name1, const char *name2, const char *label, Oid namespaceid)
Definition statscmds.c:865
void RemoveStatisticsById(Oid statsOid)
Definition statscmds.c:803
static int compare_int16(const void *a, const void *b)
Definition statscmds.c:51
Oid StatisticsGetRelation(Oid statId, bool missing_ok)
Definition statscmds.c:954
#define ERRCODE_DUPLICATE_OBJECT
Definition streamutil.c:30
Definition pg_list.h:54
Definition nodes.h:135
Form_pg_class rd_rel
Definition rel.h:111
char * name
AttrNumber varattno
Definition primnodes.h:275
Definition c.h:830
#define FirstLowInvalidHeapAttributeNumber
Definition sysattr.h:27
void ReleaseSysCache(HeapTuple tuple)
Definition syscache.c:265
HeapTuple SearchSysCache2(SysCacheIdentifier cacheId, Datum key1, Datum key2)
Definition syscache.c:231
HeapTuple SearchSysCacheAttName(Oid relid, const char *attname)
Definition syscache.c:476
HeapTuple SearchSysCache1(SysCacheIdentifier cacheId, Datum key1)
Definition syscache.c:221
#define SearchSysCacheExists2(cacheId, key1, key2)
Definition syscache.h:102
#define GetSysCacheOid2(cacheId, oidcol, key1, key2)
Definition syscache.h:111
void table_close(Relation relation, LOCKMODE lockmode)
Definition table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition table.c:40
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition typcache.c:389
#define TYPECACHE_LT_OPR
Definition typcache.h:139
#define MAX_STATISTICS_TARGET
Definition vacuum.h:350
#define intVal(v)
Definition value.h:79
#define strVal(v)
Definition value.h:82
void pull_varattnos(Node *node, Index varno, Bitmapset **varattnos)
Definition var.c:296
const char * type
const char * name