PostgreSQL Source Code git master
Loading...
Searching...
No Matches
extended_stats_funcs.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * extended_stats_funcs.c
4 * Functions for manipulating extended statistics.
5 *
6 * This file includes the set of facilities required to support the direct
7 * manipulations of extended statistics objects.
8 *
9 * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
10 * Portions Copyright (c) 1994, Regents of the University of California
11 *
12 * IDENTIFICATION
13 * src/backend/statistics/extended_stats_funcs.c
14 *
15 *-------------------------------------------------------------------------
16 */
17#include "postgres.h"
18
19#include "access/heapam.h"
20#include "catalog/indexing.h"
21#include "catalog/namespace.h"
22#include "catalog/pg_database.h"
25#include "miscadmin.h"
26#include "nodes/makefuncs.h"
27#include "nodes/nodeFuncs.h"
28#include "optimizer/optimizer.h"
31#include "utils/acl.h"
32#include "utils/array.h"
33#include "utils/builtins.h"
34#include "utils/fmgroids.h"
35#include "utils/lsyscache.h"
36#include "utils/syscache.h"
37
38
39/*
40 * Index of the arguments for the SQL functions.
41 */
56
57/*
58 * The argument names and type OIDs of the arguments for the SQL
59 * functions.
60 */
61static struct StatsArgInfo extarginfo[] =
62{
63 [RELSCHEMA_ARG] = {"schemaname", TEXTOID},
64 [RELNAME_ARG] = {"relname", TEXTOID},
65 [STATSCHEMA_ARG] = {"statistics_schemaname", TEXTOID},
66 [STATNAME_ARG] = {"statistics_name", TEXTOID},
67 [INHERITED_ARG] = {"inherited", BOOLOID},
68 [NDISTINCT_ARG] = {"n_distinct", PG_NDISTINCTOID},
69 [DEPENDENCIES_ARG] = {"dependencies", PG_DEPENDENCIESOID},
70 [MOST_COMMON_VALS_ARG] = {"most_common_vals", TEXTARRAYOID},
71 [MOST_COMMON_FREQS_ARG] = {"most_common_freqs", FLOAT8ARRAYOID},
72 [MOST_COMMON_BASE_FREQS_ARG] = {"most_common_base_freqs", FLOAT8ARRAYOID},
74};
75
77
79 const char *stxname);
81
82/*
83 * Track the extended statistics kinds expected for a pg_statistic_ext
84 * tuple.
85 */
86typedef struct
87{
90 bool mcv;
93
94static void expand_stxkind(HeapTuple tup, StakindFlags *enabled);
96 const bool *nulls,
97 const bool *replaces);
98
99static bool check_mcvlist_array(const ArrayType *arr, int argindex,
100 int required_ndims, int mcv_length);
101static Datum import_mcv(const ArrayType *mcv_arr,
102 const ArrayType *freqs_arr,
104 Oid *atttypids, int32 *atttypmods,
106 bool *ok);
107
108
109/*
110 * Fetch a pg_statistic_ext row by name and namespace OID.
111 */
112static HeapTuple
114{
115 ScanKeyData key[2];
116 SysScanDesc scan;
119
120 ScanKeyInit(&key[0],
123 F_NAMEEQ,
125 ScanKeyInit(&key[1],
128 F_OIDEQ,
130
131 /*
132 * Try to find matching pg_statistic_ext row.
133 */
136 true,
137 NULL,
138 2,
139 key);
140
141 /* Lookup is based on a unique index, so we get either 0 or 1 tuple. */
142 tup = systable_getnext(scan);
143
146
147 systable_endscan(scan);
148
149 if (!OidIsValid(stxoid))
150 return NULL;
151
153}
154
155/*
156 * Decode the stxkind column so that we know which stats types to expect,
157 * returning a StakindFlags set depending on the stats kinds expected by
158 * a pg_statistic_ext tuple.
159 */
160static void
162{
163 Datum datum;
164 ArrayType *arr;
165 char *kinds;
166
168 tup,
170 arr = DatumGetArrayTypeP(datum);
171 if (ARR_NDIM(arr) != 1 || ARR_HASNULL(arr) || ARR_ELEMTYPE(arr) != CHAROID)
172 elog(ERROR, "stxkind is not a one-dimension char array");
173
174 kinds = (char *) ARR_DATA_PTR(arr);
175
176 for (int i = 0; i < ARR_DIMS(arr)[0]; i++)
177 {
178 switch (kinds[i])
179 {
181 enabled->ndistinct = true;
182 break;
184 enabled->dependencies = true;
185 break;
186 case STATS_EXT_MCV:
187 enabled->mcv = true;
188 break;
190 enabled->expressions = true;
191 break;
192 default:
193 elog(ERROR, "incorrect stxkind %c found", kinds[i]);
194 break;
195 }
196 }
197}
198
199/*
200 * Perform the actual storage of a pg_statistic_ext_data tuple.
201 */
202static void
238
239/*
240 * Insert or update an extended statistics object.
241 *
242 * Major errors, such as the table not existing or permission errors, are
243 * reported as ERRORs. There are a couple of paths that generate a WARNING,
244 * like when the statistics object or its schema do not exist, a conversion
245 * failure on one statistic kind, or when other statistic kinds may still
246 * be updated.
247 */
248static bool
250{
251 char *relnspname;
252 char *relname;
253 Oid nspoid;
254 char *nspname;
255 char *stxname;
256 bool inherited;
259
260 StakindFlags enabled = {false, false, false, false};
261 StakindFlags has = {false, false, false, false};
262
264
266 bool nulls[Natts_pg_statistic_ext_data] = {0};
268 bool success = true;
270 bool isnull;
271 List *exprs = NIL;
272 int numattnums = 0;
273 int numexprs = 0;
274 int numattrs = 0;
275
276 /* arrays of type info, if we need them */
277 Oid *atttypids = NULL;
278 int32 *atttypmods = NULL;
280 Oid relid;
282
283 /*
284 * Fill out the StakindFlags "has" structure based on which parameters
285 * were provided to the function.
286 *
287 * The MCV stats composite value is an array of record type, but this is
288 * externally represented as three arrays that must be interleaved into
289 * the array of records (pg_stats_ext stores four arrays,
290 * most_common_val_nulls is built from the contents of most_common_vals).
291 * Therefore, none of the three array values is meaningful unless the
292 * other two are also present and in sync in terms of array length.
293 */
297 has.ndistinct = !PG_ARGISNULL(NDISTINCT_ARG);
298 has.dependencies = !PG_ARGISNULL(DEPENDENCIES_ARG);
299
300 if (RecoveryInProgress())
301 {
304 errmsg("recovery is in progress"),
305 errhint("Statistics cannot be modified during recovery."));
306 return false;
307 }
308
309 /* relation arguments */
314
315 /* extended statistics arguments */
322
323 /*
324 * First open the relation where we expect to find the statistics. This
325 * is similar to relation and attribute statistics, so as ACL checks are
326 * done before any locks are taken, even before any attempts related to
327 * the extended stats object.
328 */
332
333 nspoid = get_namespace_oid(nspname, true);
334 if (nspoid == InvalidOid)
335 {
338 errmsg("could not find schema \"%s\"", nspname));
339 success = false;
340 goto cleanup;
341 }
342
345
346 if (!HeapTupleIsValid(tup))
347 {
350 errmsg("could not find extended statistics object \"%s.%s\"",
351 nspname, stxname));
352 success = false;
353 goto cleanup;
354 }
355
357
358 /*
359 * The relation tracked by the stats object has to match with the relation
360 * we have already locked.
361 */
362 if (stxform->stxrelid != relid)
363 {
366 errmsg("could not restore extended statistics object \"%s.%s\": incorrect relation \"%s.%s\" specified",
367 nspname, stxname,
369
370 success = false;
371 goto cleanup;
372 }
373
374 /* Find out what extended statistics kinds we should expect. */
375 expand_stxkind(tup, &enabled);
376 numattnums = stxform->stxkeys.dim1;
377
378 /* decode expression (if any) */
380 tup,
382 &isnull);
383 if (!isnull)
384 {
385 char *s;
386
388 exprs = (List *) stringToNode(s);
389 pfree(s);
390
391 /*
392 * Run the expressions through eval_const_expressions(). This is not
393 * just an optimization, but is necessary, because the planner will be
394 * comparing them to similarly-processed qual clauses, and may fail to
395 * detect valid matches without this.
396 *
397 * We must not use canonicalize_qual(), however, since these are not
398 * qual expressions.
399 */
400 exprs = (List *) eval_const_expressions(NULL, (Node *) exprs);
401
402 /* May as well fix opfuncids too */
403 fix_opfuncids((Node *) exprs);
404
405 /* Compute the number of expression, for input validation. */
406 numexprs = list_length(exprs);
407 }
408
410
411 /*
412 * If the object cannot support ndistinct, we should not have data for it.
413 */
414 if (has.ndistinct && !enabled.ndistinct)
415 {
418 errmsg("cannot specify parameter \"%s\"",
420 errhint("Extended statistics object \"%s.%s\" does not support statistics of this type.",
421 nspname, stxname));
422
423 has.ndistinct = false;
424 success = false;
425 }
426
427 /*
428 * If the object cannot support dependencies, we should not have data for
429 * it.
430 */
431 if (has.dependencies && !enabled.dependencies)
432 {
435 errmsg("cannot specify parameter \"%s\"",
437 errhint("Extended statistics object \"%s.%s\" does not support statistics of this type.",
438 nspname, stxname));
439 has.dependencies = false;
440 success = false;
441 }
442
443 /*
444 * If the object cannot hold an MCV value, but any of the MCV parameters
445 * are set, then issue a WARNING and ensure that we do not try to load MCV
446 * stats later. In pg_stats_ext, most_common_val_nulls, most_common_freqs
447 * and most_common_base_freqs are NULL if most_common_vals is NULL.
448 */
449 if (!enabled.mcv)
450 {
454 {
457 errmsg("cannot specify parameters \"%s\", \"%s\" or \"%s\"",
461 errhint("Extended statistics object \"%s.%s\" does not support statistics of this type.",
462 nspname, stxname));
463
464 has.mcv = false;
465 success = false;
466 }
467 }
468 else if (!has.mcv)
469 {
470 /*
471 * If we do not have all of the MCV arrays set while the extended
472 * statistics object expects something, something is wrong. This
473 * issues a WARNING if a partial input has been provided.
474 */
478 {
481 errmsg("could not use \"%s\", \"%s\" and \"%s\": missing one or more parameters",
485 success = false;
486 }
487 }
488
489 /*
490 * Either of these statistic types requires that we supply a semi-filled
491 * VacAttrStatP array.
492 *
493 * It is not possible to use the existing lookup_var_attr_stats() and
494 * examine_attribute() because these functions will skip attributes where
495 * attstattarget is 0, and we may have statistics data to import for those
496 * attributes.
497 */
498 if (has.mcv)
499 {
501 atttypmods = palloc0_array(int32, numattrs);
503
504 /*
505 * The leading stxkeys are attribute numbers up through numattnums.
506 * These keys must be in ascending AttNumber order, but we do not rely
507 * on that.
508 */
509 for (int i = 0; i < numattnums; i++)
510 {
511 AttrNumber attnum = stxform->stxkeys.values[i];
513 ObjectIdGetDatum(relid),
515
517
518 /* Attribute not found */
520 elog(ERROR, "stxkeys references nonexistent attnum %d", attnum);
521
523
524 if (attr->attisdropped)
525 elog(ERROR, "stxkeys references dropped attnum %d", attnum);
526
527 atttypids[i] = attr->atttypid;
528 atttypmods[i] = attr->atttypmod;
529 atttypcolls[i] = attr->attcollation;
531 }
532
533 /*
534 * After all the positive number attnums in stxkeys come the negative
535 * numbers (if any) which represent expressions in the order that they
536 * appear in stxdexpr. Because the expressions are always
537 * monotonically decreasing from -1, there is no point in looking at
538 * the values in stxkeys, it's enough to know how many of them there
539 * are.
540 */
541 for (int i = numattnums; i < numattrs; i++)
542 {
543 Node *expr = list_nth(exprs, i - numattnums);
544
545 atttypids[i] = exprType(expr);
546 atttypmods[i] = exprTypmod(expr);
547 atttypcolls[i] = exprCollation(expr);
548 }
549 }
550
551 /*
552 * Populate the pg_statistic_ext_data result tuple.
553 */
554
555 /* Primary Key: cannot be NULL or replaced. */
557 nulls[Anum_pg_statistic_ext_data_stxoid - 1] = false;
560
561 /* All unspecified parameters will be left unmodified */
564 nulls[Anum_pg_statistic_ext_data_stxdmcv - 1] = true;
565 nulls[Anum_pg_statistic_ext_data_stxdexpr - 1] = true;
566
567 /*
568 * For each stats kind, deserialize the data at hand and perform a round
569 * of validation. The resulting tuple is filled with a set of updated
570 * values.
571 */
572
573 if (has.ndistinct)
574 {
578
579 if (statext_ndistinct_validate(ndistinct, &stxform->stxkeys,
581 {
585 }
586 else
587 success = false;
588
589 statext_ndistinct_free(ndistinct);
590 }
591
592 if (has.dependencies)
593 {
597
598 if (statext_dependencies_validate(dependencies, &stxform->stxkeys,
600 {
604 }
605 else
606 success = false;
607
608 statext_dependencies_free(dependencies);
609 }
610
611 if (has.mcv)
612 {
613 Datum datum;
614 bool val_ok = false;
615
619 atttypids, atttypmods, atttypcolls, numattrs,
620 &val_ok);
621
622 if (val_ok)
623 {
624 Assert(datum != (Datum) 0);
626 nulls[Anum_pg_statistic_ext_data_stxdmcv - 1] = false;
628 }
629 else
630 success = false;
631 }
632
634
635cleanup:
638 if (pg_stext != NULL)
640 if (atttypids != NULL)
642 if (atttypmods != NULL)
643 pfree(atttypmods);
644 if (atttypcolls != NULL)
646 return success;
647}
648
649/*
650 * Consistency checks to ensure that other mcvlist arrays are in alignment
651 * with the mcv array.
652 */
653static bool
654check_mcvlist_array(const ArrayType *arr, int argindex, int required_ndims,
655 int mcv_length)
656{
657 if (ARR_NDIM(arr) != required_ndims)
658 {
661 errmsg("could not parse array \"%s\": incorrect number of dimensions (%d required)",
662 extarginfo[argindex].argname, required_ndims));
663 return false;
664 }
665
666 if (array_contains_nulls(arr))
667 {
670 errmsg("could not parse array \"%s\": NULL value found",
671 extarginfo[argindex].argname));
672 return false;
673 }
674
675 if (ARR_DIMS(arr)[0] != mcv_length)
676 {
679 errmsg("could not parse array \"%s\": incorrect number of elements (same as \"%s\" required)",
680 extarginfo[argindex].argname,
682 return false;
683 }
684
685 return true;
686}
687
688/*
689 * Create the stxdmcv datum from the equal-sized arrays of most common values,
690 * their null flags, and the frequency and base frequency associated with
691 * each value.
692 */
693static Datum
695 const ArrayType *base_freqs_arr, Oid *atttypids, int32 *atttypmods,
696 Oid *atttypcolls, int numattrs, bool *ok)
697{
698 int nitems;
700 bool *mcv_nulls;
701 int check_nummcv;
702 Datum mcv = (Datum) 0;
703
704 *ok = false;
705
706 /*
707 * mcv_arr is an array of arrays. Each inner array must have the same
708 * number of elements "numattrs".
709 */
710 if (ARR_NDIM(mcv_arr) != 2)
711 {
714 errmsg("could not parse array \"%s\": incorrect number of dimensions (%d required)",
716 goto mcv_error;
717 }
718
719 if (ARR_DIMS(mcv_arr)[1] != numattrs)
720 {
723 errmsg("could not parse array \"%s\": found %d attributes but expected %d",
726 goto mcv_error;
727 }
728
729 /*
730 * "most_common_freqs" and "most_common_base_freqs" arrays must be of the
731 * same length, one-dimension and cannot contain NULLs. We use mcv_arr as
732 * the reference array for determining their length.
733 */
734 nitems = ARR_DIMS(mcv_arr)[0];
737 {
738 /* inconsistent input arrays found */
739 goto mcv_error;
740 }
741
742 /*
743 * This part builds the contents for "most_common_val_nulls", based on the
744 * values from "most_common_vals".
745 */
748
750 atttypids, atttypmods, atttypcolls,
754
755 *ok = (mcv != (Datum) 0);
756
758 return mcv;
759}
760
761/*
762 * Remove an existing pg_statistic_ext_data row for a given pg_statistic_ext
763 * row and "inherited" pair.
764 */
765static bool
767{
770 bool result = false;
771
772 /* Is there already a pg_statistic_ext_data tuple for this attribute? */
776
778 {
779 CatalogTupleDelete(sed, &oldtup->t_self);
781 result = true;
782 }
783
785
787
788 return result;
789}
790
791/*
792 * Restore (insert or replace) statistics for the given statistics object.
793 *
794 * This function accepts variadic arguments in key-value pairs, which are
795 * given to stats_fill_fcinfo_from_arg_pairs to be mapped into positional
796 * arguments.
797 */
798Datum
815
816/*
817 * Delete statistics for the given statistics object.
818 */
819Datum
821{
822 char *relnspname;
823 char *relname;
824 char *nspname;
825 Oid nspoid;
826 Oid relid;
827 char *stxname;
828 bool inherited;
833
834 /* relation arguments */
839
840 /* extended statistics arguments */
847
848 if (RecoveryInProgress())
849 {
852 errmsg("recovery is in progress"),
853 errhint("Statistics cannot be modified during recovery."));
855 }
856
857 /*
858 * First open the relation where we expect to find the statistics. This
859 * is similar to relation and attribute statistics, so as ACL checks are
860 * done before any locks are taken, even before any attempts related to
861 * the extended stats object.
862 */
866
867 /* Now check if the namespace of the stats object exists. */
868 nspoid = get_namespace_oid(nspname, true);
869 if (nspoid == InvalidOid)
870 {
873 errmsg("could not find schema \"%s\"", nspname));
875 }
876
879
880 if (!HeapTupleIsValid(tup))
881 {
885 errmsg("could not find extended statistics object \"%s.%s\"",
886 nspname, stxname));
888 }
889
891
892 /*
893 * This should be consistent, based on the lock taken on the table when we
894 * started.
895 */
896 if (stxform->stxrelid != relid)
897 {
901 errmsg("could not clear extended statistics object \"%s.%s\": incorrect relation \"%s.%s\" specified",
905 }
906
909
911
913}
#define ARR_NDIM(a)
Definition array.h:290
#define PG_GETARG_ARRAYTYPE_P(n)
Definition array.h:263
#define ARR_DATA_PTR(a)
Definition array.h:322
#define DatumGetArrayTypeP(X)
Definition array.h:261
#define ARR_ELEMTYPE(a)
Definition array.h:292
#define ARR_DIMS(a)
Definition array.h:294
#define ARR_HASNULL(a)
Definition array.h:291
bool array_contains_nulls(const ArrayType *array)
void deconstruct_array_builtin(const ArrayType *array, Oid elmtype, Datum **elemsp, bool **nullsp, int *nelemsp)
int16 AttrNumber
Definition attnum.h:21
static Datum values[MAXATTR]
Definition bootstrap.c:147
static void cleanup(void)
Definition bootstrap.c:838
#define TextDatumGetCString(d)
Definition builtins.h:99
#define Assert(condition)
Definition c.h:885
double float8
Definition c.h:656
int32_t int32
Definition c.h:554
#define OidIsValid(objectId)
Definition c.h:800
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition clauses.c:2267
MVDependencies * statext_dependencies_deserialize(bytea *data)
bool statext_dependencies_validate(const MVDependencies *dependencies, const int2vector *stxkeys, int numexprs, int elevel)
void statext_dependencies_free(MVDependencies *dependencies)
int errcode(int sqlerrcode)
Definition elog.c:874
int errmsg(const char *fmt,...)
Definition elog.c:1093
int errhint(const char *fmt,...) pg_attribute_printf(1
#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
extended_stats_argnum
@ INHERITED_ARG
@ RELSCHEMA_ARG
@ NUM_EXTENDED_STATS_ARGS
@ RELNAME_ARG
@ MOST_COMMON_BASE_FREQS_ARG
@ MOST_COMMON_FREQS_ARG
@ STATNAME_ARG
@ STATSCHEMA_ARG
@ MOST_COMMON_VALS_ARG
@ NDISTINCT_ARG
@ DEPENDENCIES_ARG
Datum pg_clear_extended_stats(PG_FUNCTION_ARGS)
static void upsert_pg_statistic_ext_data(const Datum *values, const bool *nulls, const bool *replaces)
static bool delete_pg_statistic_ext_data(Oid stxoid, bool inherited)
static struct StatsArgInfo extarginfo[]
Datum pg_restore_extended_stats(PG_FUNCTION_ARGS)
static void expand_stxkind(HeapTuple tup, StakindFlags *enabled)
static HeapTuple get_pg_statistic_ext(Relation pg_stext, Oid nspoid, const char *stxname)
static bool extended_statistics_update(FunctionCallInfo fcinfo)
static bool check_mcvlist_array(const ArrayType *arr, int argindex, int required_ndims, int mcv_length)
static Datum import_mcv(const ArrayType *mcv_arr, const ArrayType *freqs_arr, const ArrayType *base_freqs_arr, Oid *atttypids, int32 *atttypmods, Oid *atttypcolls, int numattrs, bool *ok)
#define palloc0_array(type, count)
Definition fe_memutils.h:77
#define PG_RETURN_VOID()
Definition fmgr.h:350
#define DatumGetByteaPP(X)
Definition fmgr.h:292
#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 PG_GETARG_BOOL(n)
Definition fmgr.h:274
#define PG_FUNCTION_ARGS
Definition fmgr.h:193
#define PG_RETURN_BOOL(x)
Definition fmgr.h:360
void systable_endscan(SysScanDesc sysscan)
Definition genam.c:603
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition genam.c:514
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition genam.c:388
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, const Datum *replValues, const bool *replIsnull, const bool *doReplace)
Definition heaptuple.c:1210
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
Definition heaptuple.c:1117
void heap_freetuple(HeapTuple htup)
Definition heaptuple.c:1435
#define HeapTupleIsValid(tuple)
Definition htup.h:78
static void * GETSTRUCT(const HeapTupleData *tuple)
#define nitems(x)
Definition indent.h:31
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
static bool success
Definition initdb.c:187
int i
Definition isn.c:77
#define ShareUpdateExclusiveLock
Definition lockdefs.h:39
#define RowExclusiveLock
Definition lockdefs.h:38
char * get_namespace_name(Oid nspid)
Definition lsyscache.c:3518
RangeVar * makeRangeVar(char *schemaname, char *relname, int location)
Definition makefuncs.c:473
Datum statext_mcv_import(int elevel, int numattrs, Oid *atttypids, int32 *atttypmods, Oid *atttypcolls, int nitems, Datum *mcv_elems, bool *mcv_nulls, float8 *freqs, float8 *base_freqs)
Definition mcv.c:2204
void pfree(void *pointer)
Definition mcxt.c:1616
void statext_ndistinct_free(MVNDistinct *ndistinct)
Definition mvdistinct.c:332
MVNDistinct * statext_ndistinct_deserialize(bytea *data)
Definition mvdistinct.c:247
bool statext_ndistinct_validate(const MVNDistinct *ndistinct, const int2vector *stxkeys, int numexprs, int elevel)
Definition mvdistinct.c:352
Oid get_namespace_oid(const char *nspname, bool missing_ok)
Definition namespace.c:3607
Oid RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, uint32 flags, RangeVarGetRelidCallback callback, void *callback_arg)
Definition namespace.c:442
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
void fix_opfuncids(Node *node)
Definition nodeFuncs.c:1840
int16 attnum
FormData_pg_attribute * Form_pg_attribute
NameData relname
Definition pg_class.h:40
const void * data
static int list_length(const List *l)
Definition pg_list.h:152
#define NIL
Definition pg_list.h:68
static void * list_nth(const List *list, int n)
Definition pg_list.h:299
END_CATALOG_STRUCT typedef FormData_pg_statistic_ext * Form_pg_statistic_ext
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
#define InvalidOid
unsigned int Oid
static int fb(int x)
void * stringToNode(const char *str)
Definition read.c:90
#define RelationGetDescr(relation)
Definition rel.h:540
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition scankey.c:76
bool stats_fill_fcinfo_from_arg_pairs(FunctionCallInfo pairs_fcinfo, FunctionCallInfo positional_fcinfo, struct StatsArgInfo *arginfo)
Definition stat_utils.c:348
void RangeVarCallbackForStats(const RangeVar *relation, Oid relId, Oid oldRelId, void *arg)
Definition stat_utils.c:142
void stats_check_required_arg(FunctionCallInfo fcinfo, struct StatsArgInfo *arginfo, int argnum)
Definition stat_utils.c:51
#define BTEqualStrategyNumber
Definition stratnum.h:31
Definition pg_list.h:54
Definition nodes.h:135
const char * argname
Definition stat_utils.h:24
Definition c.h:718
void ReleaseSysCache(HeapTuple tuple)
Definition syscache.c:264
HeapTuple SearchSysCache2(SysCacheIdentifier cacheId, Datum key1, Datum key2)
Definition syscache.c:230
Datum SysCacheGetAttrNotNull(SysCacheIdentifier cacheId, HeapTuple tup, AttrNumber attributeNumber)
Definition syscache.c:625
Datum SysCacheGetAttr(SysCacheIdentifier cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition syscache.c:595
#define SearchSysCacheCopy1(cacheId, key1)
Definition syscache.h:91
void table_close(Relation relation, LOCKMODE lockmode)
Definition table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition table.c:40
void CommandCounterIncrement(void)
Definition xact.c:1101
bool RecoveryInProgress(void)
Definition xlog.c:6460