PostgreSQL Source Code git master
Loading...
Searching...
No Matches
stat_utils.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 * stat_utils.c
3 *
4 * PostgreSQL statistics manipulation utilities.
5 *
6 * Code supporting the direct manipulation of statistics.
7 *
8 * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
9 * Portions Copyright (c) 1994, Regents of the University of California
10 *
11 * IDENTIFICATION
12 * src/backend/statistics/stat_utils.c
13 *
14 *-------------------------------------------------------------------------
15 */
16
17#include "postgres.h"
18
19#include "access/htup_details.h"
20#include "access/relation.h"
21#include "catalog/index.h"
22#include "catalog/namespace.h"
23#include "catalog/pg_class.h"
25#include "catalog/pg_database.h"
27#include "funcapi.h"
28#include "miscadmin.h"
29#include "nodes/nodeFuncs.h"
31#include "storage/lmgr.h"
32#include "utils/acl.h"
33#include "utils/array.h"
34#include "utils/builtins.h"
35#include "utils/lsyscache.h"
36#include "utils/rel.h"
37#include "utils/syscache.h"
38#include "utils/typcache.h"
39
40/* Default values assigned to new pg_statistic tuples. */
41#define DEFAULT_STATATT_NULL_FRAC Float4GetDatum(0.0) /* stanullfrac */
42#define DEFAULT_STATATT_AVG_WIDTH Int32GetDatum(0) /* stawidth, same as
43 * unknown */
44#define DEFAULT_STATATT_N_DISTINCT Float4GetDatum(0.0) /* stadistinct, same as
45 * unknown */
46
48
49/*
50 * Ensure that a given argument is not null.
51 */
52void
54 struct StatsArgInfo *arginfo,
55 int argnum)
56{
60 errmsg("argument \"%s\" must not be null",
61 arginfo[argnum].argname)));
62}
63
64/*
65 * Check that argument is either NULL or a one dimensional array with no
66 * NULLs.
67 *
68 * If a problem is found, emit a WARNING, and return false. Otherwise return
69 * true.
70 */
71bool
73 struct StatsArgInfo *arginfo,
74 int argnum)
75{
76 ArrayType *arr;
77
79 return true;
80
82
83 if (ARR_NDIM(arr) != 1)
84 {
87 errmsg("argument \"%s\" must not be a multidimensional array",
88 arginfo[argnum].argname)));
89 return false;
90 }
91
92 if (array_contains_nulls(arr))
93 {
96 errmsg("argument \"%s\" array must not contain null values",
97 arginfo[argnum].argname)));
98 return false;
99 }
100
101 return true;
102}
103
104/*
105 * Enforce parameter pairs that must be specified together (or not at all) for
106 * a particular stakind, such as most_common_vals and most_common_freqs for
107 * STATISTIC_KIND_MCV.
108 *
109 * If a problem is found, emit a WARNING, and return false. Otherwise return
110 * true.
111 */
112bool
114 struct StatsArgInfo *arginfo,
115 int argnum1, int argnum2)
116{
118 return true;
119
121 {
124
127 errmsg("argument \"%s\" must be specified when argument \"%s\" is specified",
128 arginfo[nullarg].argname,
129 arginfo[otherarg].argname)));
130
131 return false;
132 }
133
134 return true;
135}
136
137/*
138 * A role has privileges to set statistics on the relation if any of the
139 * following are true:
140 * - the role owns the current database and the relation is not shared
141 * - the role has the MAINTAIN privilege on the relation
142 */
143void
144RangeVarCallbackForStats(const RangeVar *relation,
145 Oid relId, Oid oldRelId, void *arg)
146{
147 Oid *locked_oid = (Oid *) arg;
148 Oid table_oid = relId;
149 HeapTuple tuple;
151 char relkind;
152
153 /*
154 * If we previously locked some other index's heap, and the name we're
155 * looking up no longer refers to that relation, release the now-useless
156 * lock.
157 */
158 if (relId != oldRelId && OidIsValid(*locked_oid))
159 {
162 }
163
164 /* If the relation does not exist, there's nothing more to do. */
165 if (!OidIsValid(relId))
166 return;
167
168 /* If the relation does exist, check whether it's an index. */
169 relkind = get_rel_relkind(relId);
170 if (relkind == RELKIND_INDEX ||
171 relkind == RELKIND_PARTITIONED_INDEX)
172 table_oid = IndexGetRelation(relId, false);
173
174 /*
175 * If retrying yields the same OID, there are a couple of extremely
176 * unlikely scenarios we need to handle.
177 */
178 if (relId == oldRelId)
179 {
180 /*
181 * If a previous lookup found an index, but the current lookup did
182 * not, the index was dropped and the OID was reused for something
183 * else between lookups. In theory, we could simply drop our lock on
184 * the index's parent table and proceed, but in the interest of
185 * avoiding complexity, we just error.
186 */
187 if (table_oid == relId && OidIsValid(*locked_oid))
190 errmsg("index \"%s\" was concurrently dropped",
191 relation->relname)));
192
193 /*
194 * If the current lookup found an index but a previous lookup either
195 * did not find an index or found one with a different parent
196 * relation, the relation was dropped and the OID was reused for an
197 * index between lookups. RangeVarGetRelidExtended() will have
198 * already locked the index at this point, so we can't just lock the
199 * newly discovered parent table OID without risking deadlock. As
200 * above, we just error in this case.
201 */
202 if (table_oid != relId && table_oid != *locked_oid)
205 errmsg("index \"%s\" was concurrently created",
206 relation->relname)));
207 }
208
210 if (!HeapTupleIsValid(tuple))
211 elog(ERROR, "cache lookup failed for OID %u", table_oid);
212 form = (Form_pg_class) GETSTRUCT(tuple);
213
214 /* the relkinds that can be used with ANALYZE */
215 switch (form->relkind)
216 {
217 case RELKIND_RELATION:
218 case RELKIND_MATVIEW:
221 break;
222 default:
225 errmsg("cannot modify statistics for relation \"%s\"",
226 NameStr(form->relname)),
228 }
229
230 if (form->relisshared)
233 errmsg("cannot modify statistics for shared relation")));
234
235 /* Check permissions */
237 {
239 GetUserId(),
241
242 if (aclresult != ACLCHECK_OK)
244 get_relkind_objtype(form->relkind),
245 NameStr(form->relname));
246 }
247
248 ReleaseSysCache(tuple);
249
250 /* Lock heap before index to avoid deadlock. */
251 if (relId != oldRelId && table_oid != relId)
252 {
255 }
256}
257
258
259/*
260 * Find the argument number for the given argument name, returning -1 if not
261 * found.
262 */
263static int
264get_arg_by_name(const char *argname, struct StatsArgInfo *arginfo)
265{
266 int argnum;
267
268 for (argnum = 0; arginfo[argnum].argname != NULL; argnum++)
269 if (pg_strcasecmp(argname, arginfo[argnum].argname) == 0)
270 return argnum;
271
273 (errmsg("unrecognized argument name: \"%s\"", argname)));
274
275 return -1;
276}
277
278/*
279 * Ensure that a given argument matched the expected type.
280 */
281static bool
282stats_check_arg_type(const char *argname, Oid argtype, Oid expectedtype)
283{
284 if (argtype != expectedtype)
285 {
287 (errmsg("argument \"%s\" has type %s, expected type %s",
288 argname, format_type_be(argtype),
290 return false;
291 }
292
293 return true;
294}
295
296/*
297 * Check if attribute of an index is an expression, then retrieve the
298 * expression if is it the case.
299 *
300 * If the attnum specified is known to be an expression, then we must
301 * walk the list attributes up to the specified attnum to get the right
302 * expression.
303 */
304static Node *
306{
309
310 /* relation is not an index */
311 if (rel->rd_rel->relkind != RELKIND_INDEX &&
312 rel->rd_rel->relkind != RELKIND_PARTITIONED_INDEX)
313 return NULL;
314
316
317 /* index has no expressions to give */
318 if (index_exprs == NIL)
319 return NULL;
320
321 /*
322 * The index's attnum points directly to a relation attnum, hence it is
323 * not an expression attribute.
324 */
325 if (rel->rd_index->indkey.values[attnum - 1] != 0)
326 return NULL;
327
329
330 for (int i = 0; i < attnum - 1; i++)
331 if (rel->rd_index->indkey.values[i] == 0)
333
334 if (indexpr_item == NULL) /* shouldn't happen */
335 elog(ERROR, "too few entries in indexprs list");
336
337 return (Node *) lfirst(indexpr_item);
338}
339
340/*
341 * Translate variadic argument pairs from 'pairs_fcinfo' into a
342 * 'positional_fcinfo' appropriate for calling relation_statistics_update() or
343 * attribute_statistics_update() with positional arguments.
344 *
345 * Caller should have already initialized positional_fcinfo with a size
346 * appropriate for calling the intended positional function, and arginfo
347 * should also match the intended positional function.
348 */
349bool
352 struct StatsArgInfo *arginfo)
353{
354 Datum *args;
355 bool *argnulls;
356 Oid *types;
357 int nargs;
358 bool result = true;
359
360 /* clear positional args */
361 for (int i = 0; arginfo[i].argname != NULL; i++)
362 {
363 positional_fcinfo->args[i].value = (Datum) 0;
364 positional_fcinfo->args[i].isnull = true;
365 }
366
367 nargs = extract_variadic_args(pairs_fcinfo, 0, true,
368 &args, &types, &argnulls);
369
370 if (nargs % 2 != 0)
372 errmsg("variadic arguments must be name/value pairs"),
373 errhint("Provide an even number of variadic arguments that can be divided into pairs."));
374
375 /*
376 * For each argument name/value pair, find corresponding positional
377 * argument for the argument name, and assign the argument value to
378 * positional_fcinfo.
379 */
380 for (int i = 0; i < nargs; i += 2)
381 {
382 int argnum;
383 char *argname;
384
385 if (argnulls[i])
387 (errmsg("name at variadic position %d is null", i + 1)));
388
389 if (types[i] != TEXTOID)
391 (errmsg("name at variadic position %d has type %s, expected type %s",
392 i + 1, format_type_be(types[i]),
394
395 if (argnulls[i + 1])
396 continue;
397
398 argname = TextDatumGetCString(args[i]);
399
400 /*
401 * The 'version' argument is a special case, not handled by arginfo
402 * because it's not a valid positional argument.
403 *
404 * For now, 'version' is accepted but ignored. In the future it can be
405 * used to interpret older statistics properly.
406 */
407 if (pg_strcasecmp(argname, "version") == 0)
408 continue;
409
410 argnum = get_arg_by_name(argname, arginfo);
411
412 if (argnum < 0 || !stats_check_arg_type(argname, types[i + 1],
413 arginfo[argnum].argtype))
414 {
415 result = false;
416 continue;
417 }
418
419 positional_fcinfo->args[argnum].value = args[i + 1];
420 positional_fcinfo->args[argnum].isnull = false;
421 }
422
423 return result;
424}
425
426/*
427 * Derive type information from a relation attribute.
428 *
429 * This is needed for setting most slot statistics for all data types.
430 *
431 * This duplicates the logic in examine_attribute() but it will not skip the
432 * attribute if the attstattarget is 0.
433 *
434 * This information, retrieved from pg_attribute and pg_type with some
435 * specific handling for index expressions, is a prerequisite to calling
436 * any of the other statatt_*() functions.
437 */
438void
440 Oid *atttypid, int32 *atttypmod,
441 char *atttyptype, Oid *atttypcoll,
442 Oid *eq_opr, Oid *lt_opr)
443{
447 Node *expr;
448 TypeCacheEntry *typcache;
449
452
453 /* Attribute not found */
457 errmsg("column %d of relation \"%s\" does not exist",
459
461
462 if (attr->attisdropped)
465 errmsg("column %d of relation \"%s\" does not exist",
467
468 expr = statatt_get_index_expr(rel, attr->attnum);
469
470 /*
471 * When analyzing an expression index, believe the expression tree's type
472 * not the column datatype --- the latter might be the opckeytype storage
473 * type of the opclass, which is not interesting for our purposes. This
474 * mimics the behavior of examine_attribute().
475 */
476 if (expr == NULL)
477 {
478 *atttypid = attr->atttypid;
479 *atttypmod = attr->atttypmod;
480 *atttypcoll = attr->attcollation;
481 }
482 else
483 {
484 *atttypid = exprType(expr);
485 *atttypmod = exprTypmod(expr);
486
487 if (OidIsValid(attr->attcollation))
488 *atttypcoll = attr->attcollation;
489 else
490 *atttypcoll = exprCollation(expr);
491 }
493
494 /*
495 * If it's a multirange, step down to the range type, as is done by
496 * multirange_typanalyze().
497 */
500
501 /* finds the right operators even if atttypid is a domain */
503 *atttyptype = typcache->typtype;
504 *eq_opr = typcache->eq_opr;
505 *lt_opr = typcache->lt_opr;
506
507 /*
508 * Special case: collation for tsvector is DEFAULT_COLLATION_OID. See
509 * compute_tsvector_stats().
510 */
511 if (*atttypid == TSVECTOROID)
513
515}
516
517/*
518 * Derive element type information from the attribute type. This information
519 * is needed when the given type is one that contains elements of other types.
520 *
521 * The atttypid and atttyptype should be derived from a previous call to
522 * statatt_get_type().
523 */
524bool
527{
529
530 if (atttypid == TSVECTOROID)
531 {
532 /*
533 * Special case: element type for tsvector is text. See
534 * compute_tsvector_stats().
535 */
537 }
538 else
539 {
540 /* find underlying element type through any domain */
542 }
543
544 if (!OidIsValid(*elemtypid))
545 return false;
546
547 /* finds the right operator even if elemtypid is a domain */
549 if (!OidIsValid(elemtypcache->eq_opr))
550 return false;
551
552 *elem_eq_opr = elemtypcache->eq_opr;
553
554 return true;
555}
556
557/*
558 * Build an array with element type elemtypid from a text datum, used as
559 * value of an attribute in a tuple to-be-inserted into pg_statistic.
560 *
561 * The typid and typmod should be derived from a previous call to
562 * statatt_get_type().
563 *
564 * If an error is encountered, capture it and throw a WARNING, with "ok" set
565 * to false. If the resulting array contains NULLs, raise a WARNING and
566 * set "ok" to false. When the operation succeeds, set "ok" to true.
567 */
568Datum
570 int32 typmod, bool *ok)
571{
572 LOCAL_FCINFO(fcinfo, 8);
573 char *s;
574 Datum result;
576
577 escontext.details_wanted = true;
578
579 s = TextDatumGetCString(d);
580
582 (Node *) &escontext, NULL);
583
584 fcinfo->args[0].value = CStringGetDatum(s);
585 fcinfo->args[0].isnull = false;
586 fcinfo->args[1].value = ObjectIdGetDatum(typid);
587 fcinfo->args[1].isnull = false;
588 fcinfo->args[2].value = Int32GetDatum(typmod);
589 fcinfo->args[2].isnull = false;
590
591 result = FunctionCallInvoke(fcinfo);
592
593 pfree(s);
594
595 if (escontext.error_occurred)
596 {
597 escontext.error_data->elevel = WARNING;
598 ThrowErrorData(escontext.error_data);
599 *ok = false;
600 return (Datum) 0;
601 }
602
604 {
607 errmsg("\"%s\" array must not contain null values", staname)));
608 *ok = false;
609 return (Datum) 0;
610 }
611
612 *ok = true;
613
614 return result;
615}
616
617/*
618 * Find and update the slot of a stakind, or use the first empty slot.
619 *
620 * Core statistics types expect the stakind value to be one of the
621 * STATISTIC_KIND_* constants defined in pg_statistic.h, but types defined
622 * by extensions are not restricted to those values.
623 *
624 * In the case of core statistics, the required staop is determined by the
625 * stakind given and will either be a hardcoded oid, or the eq/lt operator
626 * derived from statatt_get_type(). Likewise, types defined by extensions
627 * have no such restriction.
628 *
629 * The stacoll value should be either the atttypcoll derived from
630 * statatt_get_type(), or a hardcoded value required by that particular
631 * stakind.
632 *
633 * The value/null pairs for stanumbers and stavalues should be calculated
634 * based on the stakind, using statatt_build_stavalues() or constructed arrays.
635 */
636void
637statatt_set_slot(Datum *values, bool *nulls, bool *replaces,
638 int16 stakind, Oid staop, Oid stacoll,
639 Datum stanumbers, bool stanumbers_isnull,
640 Datum stavalues, bool stavalues_isnull)
641{
642 int slotidx;
643 int first_empty = -1;
647
648 /* find existing slot with given stakind */
650 {
652
653 if (first_empty < 0 &&
656 if (DatumGetInt16(values[stakind_attnum]) == stakind)
657 break;
658 }
659
662
665 (errmsg("maximum number of statistics slots exceeded: %d",
666 slotidx + 1)));
667
671
672 if (DatumGetInt16(values[stakind_attnum]) != stakind)
673 {
675 replaces[stakind_attnum] = true;
676 }
677 if (DatumGetObjectId(values[staop_attnum]) != staop)
678 {
680 replaces[staop_attnum] = true;
681 }
682 if (DatumGetObjectId(values[stacoll_attnum]) != stacoll)
683 {
685 replaces[stacoll_attnum] = true;
686 }
688 {
689 values[Anum_pg_statistic_stanumbers1 - 1 + slotidx] = stanumbers;
690 nulls[Anum_pg_statistic_stanumbers1 - 1 + slotidx] = false;
692 }
693 if (!stavalues_isnull)
694 {
696 nulls[Anum_pg_statistic_stavalues1 - 1 + slotidx] = false;
698 }
699}
700
701/*
702 * Initialize values and nulls for a new pg_statistic tuple.
703 *
704 * The caller is responsible for allocating the arrays where the results are
705 * stored, which should be of size Natts_pg_statistic.
706 *
707 * When using this routine for a tuple inserted into pg_statistic, reloid,
708 * attnum and inherited flags should all be set.
709 *
710 * When using this routine for a tuple that is an element of a stxdexpr
711 * array inserted into pg_statistic_ext_data, reloid, attnum and inherited
712 * should be respectively set to InvalidOid, InvalidAttrNumber and false.
713 */
714void
716 Datum *values, bool *nulls, bool *replaces)
717{
718 memset(nulls, true, sizeof(bool) * Natts_pg_statistic);
719 memset(replaces, true, sizeof(bool) * Natts_pg_statistic);
720
721 /* This must initialize non-NULL attributes */
723 nulls[Anum_pg_statistic_starelid - 1] = false;
725 nulls[Anum_pg_statistic_staattnum - 1] = false;
727 nulls[Anum_pg_statistic_stainherit - 1] = false;
728
730 nulls[Anum_pg_statistic_stanullfrac - 1] = false;
732 nulls[Anum_pg_statistic_stawidth - 1] = false;
734 nulls[Anum_pg_statistic_stadistinct - 1] = false;
735
736 /* initialize stakind, staop, and stacoll slots */
737 for (int slotnum = 0; slotnum < STATISTIC_NUM_SLOTS; slotnum++)
738 {
740 nulls[Anum_pg_statistic_stakind1 + slotnum - 1] = false;
742 nulls[Anum_pg_statistic_staop1 + slotnum - 1] = false;
744 nulls[Anum_pg_statistic_stacoll1 + slotnum - 1] = false;
745 }
746}
AclResult
Definition acl.h:182
@ ACLCHECK_OK
Definition acl.h:183
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition aclchk.c:2654
bool object_ownercheck(Oid classid, Oid objectid, Oid roleid)
Definition aclchk.c:4090
AclResult pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode)
Definition aclchk.c:4039
#define ARR_NDIM(a)
Definition array.h:290
#define DatumGetArrayTypeP(X)
Definition array.h:261
bool array_contains_nulls(const ArrayType *array)
Datum array_in(PG_FUNCTION_ARGS)
Definition arrayfuncs.c:180
int16 AttrNumber
Definition attnum.h:21
static Datum values[MAXATTR]
Definition bootstrap.c:155
#define TextDatumGetCString(d)
Definition builtins.h:98
#define NameStr(name)
Definition c.h:765
int16_t int16
Definition c.h:541
int32_t int32
Definition c.h:542
#define OidIsValid(objectId)
Definition c.h:788
struct typedefs * types
Definition ecpg.c:30
int errhint(const char *fmt,...)
Definition elog.c:1330
void ThrowErrorData(ErrorData *edata)
Definition elog.c:1912
int errcode(int sqlerrcode)
Definition elog.c:863
int errmsg(const char *fmt,...)
Definition elog.c:1080
#define WARNING
Definition elog.h:36
#define ERROR
Definition elog.h:39
#define elog(elevel,...)
Definition elog.h:226
#define ereport(elevel,...)
Definition elog.h:150
#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo)
Definition fmgr.h:150
#define PG_ARGISNULL(n)
Definition fmgr.h:209
#define PG_GETARG_DATUM(n)
Definition fmgr.h:268
#define LOCAL_FCINFO(name, nargs)
Definition fmgr.h:110
#define FunctionCallInvoke(fcinfo)
Definition fmgr.h:172
char * format_type_be(Oid type_oid)
int extract_variadic_args(FunctionCallInfo fcinfo, int variadic_start, bool convert_unknown, Datum **args, Oid **types, bool **nulls)
Definition funcapi.c:2005
Oid MyDatabaseId
Definition globals.c:94
#define HeapTupleIsValid(tuple)
Definition htup.h:78
static void * GETSTRUCT(const HeapTupleData *tuple)
Oid IndexGetRelation(Oid indexId, bool missing_ok)
Definition index.c:3581
int i
Definition isn.c:77
void UnlockRelationOid(Oid relid, LOCKMODE lockmode)
Definition lmgr.c:229
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition lmgr.c:107
#define NoLock
Definition lockdefs.h:34
#define AccessShareLock
Definition lockdefs.h:36
#define ShareUpdateExclusiveLock
Definition lockdefs.h:39
Oid get_multirange_range(Oid multirangeOid)
Definition lsyscache.c:3633
char get_rel_relkind(Oid relid)
Definition lsyscache.c:2153
Oid get_base_element_type(Oid typid)
Definition lsyscache.c:2982
bool type_is_multirange(Oid typid)
Definition lsyscache.c:2848
void pfree(void *pointer)
Definition mcxt.c:1616
Oid GetUserId(void)
Definition miscinit.c:469
Oid exprType(const Node *expr)
Definition nodeFuncs.c:42
int32 exprTypmod(const Node *expr)
Definition nodeFuncs.c:301
Oid exprCollation(const Node *expr)
Definition nodeFuncs.c:821
ObjectType get_relkind_objtype(char relkind)
#define ACL_MAINTAIN
Definition parsenodes.h:90
int16 attnum
FormData_pg_attribute * Form_pg_attribute
void * arg
int errdetail_relkind_not_supported(char relkind)
Definition pg_class.c:24
FormData_pg_class * Form_pg_class
Definition pg_class.h:156
#define lfirst(lc)
Definition pg_list.h:172
#define NIL
Definition pg_list.h:68
static ListCell * list_head(const List *l)
Definition pg_list.h:128
static ListCell * lnext(const List *l, const ListCell *c)
Definition pg_list.h:343
#define STATISTIC_NUM_SLOTS
int pg_strcasecmp(const char *s1, const char *s2)
static Oid DatumGetObjectId(Datum X)
Definition postgres.h:252
static Datum Int16GetDatum(int16 X)
Definition postgres.h:182
static Datum BoolGetDatum(bool X)
Definition postgres.h:112
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:262
uint64_t Datum
Definition postgres.h:70
static Datum CStringGetDatum(const char *X)
Definition postgres.h:380
static Datum Int32GetDatum(int32 X)
Definition postgres.h:222
static int16 DatumGetInt16(Datum X)
Definition postgres.h:172
#define InvalidOid
unsigned int Oid
static int fb(int x)
#define RelationGetRelationName(relation)
Definition rel.h:548
List * RelationGetIndexExpressions(Relation relation)
Definition relcache.c:5092
void relation_close(Relation relation, LOCKMODE lockmode)
Definition relation.c:205
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition relation.c:47
#define DEFAULT_STATATT_NULL_FRAC
Definition stat_utils.c:41
bool statatt_get_elem_type(Oid atttypid, char atttyptype, Oid *elemtypid, Oid *elem_eq_opr)
Definition stat_utils.c:523
Datum statatt_build_stavalues(const char *staname, FmgrInfo *array_in, Datum d, Oid typid, int32 typmod, bool *ok)
Definition stat_utils.c:567
bool stats_fill_fcinfo_from_arg_pairs(FunctionCallInfo pairs_fcinfo, FunctionCallInfo positional_fcinfo, struct StatsArgInfo *arginfo)
Definition stat_utils.c:348
static int get_arg_by_name(const char *argname, struct StatsArgInfo *arginfo)
Definition stat_utils.c:262
void RangeVarCallbackForStats(const RangeVar *relation, Oid relId, Oid oldRelId, void *arg)
Definition stat_utils.c:142
void statatt_init_empty_tuple(Oid reloid, int16 attnum, bool inherited, Datum *values, bool *nulls, bool *replaces)
Definition stat_utils.c:713
#define DEFAULT_STATATT_AVG_WIDTH
Definition stat_utils.c:42
static bool stats_check_arg_type(const char *argname, Oid argtype, Oid expectedtype)
Definition stat_utils.c:280
bool stats_check_arg_array(FunctionCallInfo fcinfo, struct StatsArgInfo *arginfo, int argnum)
Definition stat_utils.c:70
void statatt_get_type(Oid reloid, AttrNumber attnum, Oid *atttypid, int32 *atttypmod, char *atttyptype, Oid *atttypcoll, Oid *eq_opr, Oid *lt_opr)
Definition stat_utils.c:437
void stats_check_required_arg(FunctionCallInfo fcinfo, struct StatsArgInfo *arginfo, int argnum)
Definition stat_utils.c:51
static Node * statatt_get_index_expr(Relation rel, int attnum)
Definition stat_utils.c:303
#define DEFAULT_STATATT_N_DISTINCT
Definition stat_utils.c:43
void statatt_set_slot(Datum *values, bool *nulls, bool *replaces, int16 stakind, Oid staop, Oid stacoll, Datum stanumbers, bool stanumbers_isnull, Datum stavalues, bool stavalues_isnull)
Definition stat_utils.c:635
bool stats_check_arg_pair(FunctionCallInfo fcinfo, struct StatsArgInfo *arginfo, int argnum1, int argnum2)
Definition stat_utils.c:111
int elevel
Definition elog.h:421
ErrorData * error_data
Definition miscnodes.h:49
Definition pg_list.h:54
Definition nodes.h:135
char * relname
Definition primnodes.h:83
List * rd_indexprs
Definition rel.h:212
Form_pg_index rd_index
Definition rel.h:192
Form_pg_class rd_rel
Definition rel.h:111
void ReleaseSysCache(HeapTuple tuple)
Definition syscache.c:264
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition syscache.c:220
HeapTuple SearchSysCache2(int cacheId, Datum key1, Datum key2)
Definition syscache.c:230
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition typcache.c:386
#define TYPECACHE_EQ_OPR
Definition typcache.h:138
#define TYPECACHE_LT_OPR
Definition typcache.h:139