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_collation_d.h"
23#include "catalog/pg_database.h"
24#include "catalog/pg_operator.h"
27#include "miscadmin.h"
28#include "nodes/makefuncs.h"
29#include "nodes/nodeFuncs.h"
30#include "optimizer/optimizer.h"
33#include "utils/acl.h"
34#include "utils/array.h"
35#include "utils/builtins.h"
36#include "utils/fmgroids.h"
37#include "utils/jsonb.h"
38#include "utils/lsyscache.h"
39#include "utils/syscache.h"
40#include "utils/typcache.h"
41
42
43/*
44 * Index of the arguments for the SQL functions.
45 */
61
62/*
63 * The argument names and type OIDs of the arguments for the SQL
64 * functions.
65 */
66static struct StatsArgInfo extarginfo[] =
67{
68 [RELSCHEMA_ARG] = {"schemaname", TEXTOID},
69 [RELNAME_ARG] = {"relname", TEXTOID},
70 [STATSCHEMA_ARG] = {"statistics_schemaname", TEXTOID},
71 [STATNAME_ARG] = {"statistics_name", TEXTOID},
72 [INHERITED_ARG] = {"inherited", BOOLOID},
73 [NDISTINCT_ARG] = {"n_distinct", PG_NDISTINCTOID},
74 [DEPENDENCIES_ARG] = {"dependencies", PG_DEPENDENCIESOID},
75 [MOST_COMMON_VALS_ARG] = {"most_common_vals", TEXTARRAYOID},
76 [MOST_COMMON_FREQS_ARG] = {"most_common_freqs", FLOAT8ARRAYOID},
77 [MOST_COMMON_BASE_FREQS_ARG] = {"most_common_base_freqs", FLOAT8ARRAYOID},
78 [EXPRESSIONS_ARG] = {"exprs", JSONBOID},
80};
81
82/*
83 * An index of the elements of a stxdexpr Datum, which repeat for each
84 * expression in the extended statistics object.
85 */
103
104/*
105 * The argument names of the repeating arguments for stxdexpr.
106 */
108{
109 "null_frac",
110 "avg_width",
111 "n_distinct",
112 "most_common_vals",
113 "most_common_freqs",
114 "histogram_bounds",
115 "correlation",
116 "most_common_elems",
117 "most_common_elem_freqs",
118 "elem_count_histogram",
119 "range_length_histogram",
120 "range_empty_frac",
121 "range_bounds_histogram"
122};
123
125
127 const char *stxname);
129
130/*
131 * Track the extended statistics kinds expected for a pg_statistic_ext
132 * tuple.
133 */
134typedef struct
135{
138 bool mcv;
141
142static void expand_stxkind(HeapTuple tup, StakindFlags *enabled);
143static void upsert_pg_statistic_ext_data(const Datum *values,
144 const bool *nulls,
145 const bool *replaces);
146
147static bool check_mcvlist_array(const ArrayType *arr, int argindex,
148 int required_ndims, int mcv_length);
150 Oid *atttypids, int32 *atttypmods,
152 bool *exprs_is_perfect);
153static Datum import_mcv(const ArrayType *mcv_arr,
154 const ArrayType *freqs_arr,
156 Oid *atttypids, int32 *atttypmods,
158 bool *ok);
159
160static char *jbv_string_get_cstr(JsonbValue *jval);
162 AttrNumber exprnum, const char *argname,
163 Datum *datum);
164static bool key_in_expr_argnames(JsonbValue *key);
166static Datum array_in_safe(FmgrInfo *array_in, const char *s, Oid typid,
167 int32 typmod, AttrNumber exprnum,
168 const char *element_name, bool *ok);
171 Oid typid, int32 typmod, Oid typcoll,
172 bool *pg_statistic_ok);
173
174/*
175 * Fetch a pg_statistic_ext row by name and namespace OID.
176 */
177static HeapTuple
179{
180 ScanKeyData key[2];
181 SysScanDesc scan;
184
185 ScanKeyInit(&key[0],
188 F_NAMEEQ,
190 ScanKeyInit(&key[1],
193 F_OIDEQ,
195
196 /*
197 * Try to find matching pg_statistic_ext row.
198 */
201 true,
202 NULL,
203 2,
204 key);
205
206 /* Lookup is based on a unique index, so we get either 0 or 1 tuple. */
207 tup = systable_getnext(scan);
208
211
212 systable_endscan(scan);
213
214 if (!OidIsValid(stxoid))
215 return NULL;
216
218}
219
220/*
221 * Decode the stxkind column so that we know which stats types to expect,
222 * returning a StakindFlags set depending on the stats kinds expected by
223 * a pg_statistic_ext tuple.
224 */
225static void
227{
228 Datum datum;
229 ArrayType *arr;
230 char *kinds;
231
233 tup,
235 arr = DatumGetArrayTypeP(datum);
236 if (ARR_NDIM(arr) != 1 || ARR_HASNULL(arr) || ARR_ELEMTYPE(arr) != CHAROID)
237 elog(ERROR, "stxkind is not a one-dimension char array");
238
239 kinds = (char *) ARR_DATA_PTR(arr);
240
241 for (int i = 0; i < ARR_DIMS(arr)[0]; i++)
242 {
243 switch (kinds[i])
244 {
246 enabled->ndistinct = true;
247 break;
249 enabled->dependencies = true;
250 break;
251 case STATS_EXT_MCV:
252 enabled->mcv = true;
253 break;
255 enabled->expressions = true;
256 break;
257 default:
258 elog(ERROR, "incorrect stxkind %c found", kinds[i]);
259 break;
260 }
261 }
262}
263
264/*
265 * Perform the actual storage of a pg_statistic_ext_data tuple.
266 */
267static void
303
304/*
305 * Insert or update an extended statistics object.
306 *
307 * Major errors, such as the table not existing or permission errors, are
308 * reported as ERRORs. There are a couple of paths that generate a WARNING,
309 * like when the statistics object or its schema do not exist, a conversion
310 * failure on one statistic kind, or when other statistic kinds may still
311 * be updated.
312 */
313static bool
315{
316 char *relnspname;
317 char *relname;
318 Oid nspoid;
319 char *nspname;
320 char *stxname;
321 bool inherited;
324
325 StakindFlags enabled = {false, false, false, false};
326 StakindFlags has = {false, false, false, false};
327
329
331 bool nulls[Natts_pg_statistic_ext_data] = {0};
333 bool success = true;
335 bool isnull;
336 List *exprs = NIL;
337 int numattnums = 0;
338 int numexprs = 0;
339 int numattrs = 0;
340
341 /* arrays of type info, if we need them */
342 Oid *atttypids = NULL;
343 int32 *atttypmods = NULL;
345 Oid relid;
347
348 /*
349 * Fill out the StakindFlags "has" structure based on which parameters
350 * were provided to the function.
351 *
352 * The MCV stats composite value is an array of record type, but this is
353 * externally represented as three arrays that must be interleaved into
354 * the array of records (pg_stats_ext stores four arrays,
355 * most_common_val_nulls is built from the contents of most_common_vals).
356 * Therefore, none of the three array values is meaningful unless the
357 * other two are also present and in sync in terms of array length.
358 */
362 has.ndistinct = !PG_ARGISNULL(NDISTINCT_ARG);
363 has.dependencies = !PG_ARGISNULL(DEPENDENCIES_ARG);
364 has.expressions = !PG_ARGISNULL(EXPRESSIONS_ARG);
365
366 if (RecoveryInProgress())
367 {
370 errmsg("recovery is in progress"),
371 errhint("Statistics cannot be modified during recovery."));
372 return false;
373 }
374
375 /* relation arguments */
380
381 /* extended statistics arguments */
388
389 /*
390 * First open the relation where we expect to find the statistics. This
391 * is similar to relation and attribute statistics, so as ACL checks are
392 * done before any locks are taken, even before any attempts related to
393 * the extended stats object.
394 */
398
399 nspoid = get_namespace_oid(nspname, true);
400 if (nspoid == InvalidOid)
401 {
404 errmsg("could not find schema \"%s\"", nspname));
405 success = false;
406 goto cleanup;
407 }
408
411
412 if (!HeapTupleIsValid(tup))
413 {
416 errmsg("could not find extended statistics object \"%s.%s\"",
417 nspname, stxname));
418 success = false;
419 goto cleanup;
420 }
421
423
424 /*
425 * The relation tracked by the stats object has to match with the relation
426 * we have already locked.
427 */
428 if (stxform->stxrelid != relid)
429 {
432 errmsg("could not restore extended statistics object \"%s.%s\": incorrect relation \"%s.%s\" specified",
433 nspname, stxname,
435
436 success = false;
437 goto cleanup;
438 }
439
440 /* Find out what extended statistics kinds we should expect. */
441 expand_stxkind(tup, &enabled);
442 numattnums = stxform->stxkeys.dim1;
443
444 /* decode expression (if any) */
446 tup,
448 &isnull);
449 if (!isnull)
450 {
451 char *s;
452
454 exprs = (List *) stringToNode(s);
455 pfree(s);
456
457 /*
458 * Run the expressions through eval_const_expressions(). This is not
459 * just an optimization, but is necessary, because the planner will be
460 * comparing them to similarly-processed qual clauses, and may fail to
461 * detect valid matches without this.
462 *
463 * We must not use canonicalize_qual(), however, since these are not
464 * qual expressions.
465 */
466 exprs = (List *) eval_const_expressions(NULL, (Node *) exprs);
467
468 /* May as well fix opfuncids too */
469 fix_opfuncids((Node *) exprs);
470
471 /* Compute the number of expression, for input validation. */
472 numexprs = list_length(exprs);
473 }
474
476
477 /*
478 * If the object cannot support ndistinct, we should not have data for it.
479 */
480 if (has.ndistinct && !enabled.ndistinct)
481 {
484 errmsg("cannot specify parameter \"%s\"",
486 errhint("Extended statistics object \"%s.%s\" does not support statistics of this type.",
487 nspname, stxname));
488
489 has.ndistinct = false;
490 success = false;
491 }
492
493 /*
494 * If the object cannot support dependencies, we should not have data for
495 * it.
496 */
497 if (has.dependencies && !enabled.dependencies)
498 {
501 errmsg("cannot specify parameter \"%s\"",
503 errhint("Extended statistics object \"%s.%s\" does not support statistics of this type.",
504 nspname, stxname));
505 has.dependencies = false;
506 success = false;
507 }
508
509 /*
510 * If the object cannot hold an MCV value, but any of the MCV parameters
511 * are set, then issue a WARNING and ensure that we do not try to load MCV
512 * stats later. In pg_stats_ext, most_common_val_nulls, most_common_freqs
513 * and most_common_base_freqs are NULL if most_common_vals is NULL.
514 */
515 if (!enabled.mcv)
516 {
520 {
523 errmsg("cannot specify parameters \"%s\", \"%s\" or \"%s\"",
527 errhint("Extended statistics object \"%s.%s\" does not support statistics of this type.",
528 nspname, stxname));
529
530 has.mcv = false;
531 success = false;
532 }
533 }
534 else if (!has.mcv)
535 {
536 /*
537 * If we do not have all of the MCV arrays set while the extended
538 * statistics object expects something, something is wrong. This
539 * issues a WARNING if a partial input has been provided.
540 */
544 {
547 errmsg("could not use \"%s\", \"%s\" and \"%s\": missing one or more parameters",
551 success = false;
552 }
553 }
554
555 /*
556 * If the object cannot support expressions, we should not have data for
557 * them.
558 */
559 if (has.expressions && !enabled.expressions)
560 {
563 errmsg("cannot specify parameter \"%s\"",
565 errhint("Extended statistics object \"%s.%s\" does not support statistics of this type.",
566 nspname, stxname));
567
568 has.expressions = false;
569 success = false;
570 }
571
572 /*
573 * Either of these statistic types requires that we supply a semi-filled
574 * VacAttrStatP array.
575 *
576 * It is not possible to use the existing lookup_var_attr_stats() and
577 * examine_attribute() because these functions will skip attributes where
578 * attstattarget is 0, and we may have statistics data to import for those
579 * attributes.
580 */
581 if (has.mcv || has.expressions)
582 {
584 atttypmods = palloc0_array(int32, numattrs);
586
587 /*
588 * The leading stxkeys are attribute numbers up through numattnums.
589 * These keys must be in ascending AttNumber order, but we do not rely
590 * on that.
591 */
592 for (int i = 0; i < numattnums; i++)
593 {
594 AttrNumber attnum = stxform->stxkeys.values[i];
596 ObjectIdGetDatum(relid),
598
600
601 /* Attribute not found */
603 elog(ERROR, "stxkeys references nonexistent attnum %d", attnum);
604
606
607 if (attr->attisdropped)
608 elog(ERROR, "stxkeys references dropped attnum %d", attnum);
609
610 atttypids[i] = attr->atttypid;
611 atttypmods[i] = attr->atttypmod;
612 atttypcolls[i] = attr->attcollation;
614 }
615
616 /*
617 * After all the positive number attnums in stxkeys come the negative
618 * numbers (if any) which represent expressions in the order that they
619 * appear in stxdexpr. Because the expressions are always
620 * monotonically decreasing from -1, there is no point in looking at
621 * the values in stxkeys, it's enough to know how many of them there
622 * are.
623 */
624 for (int i = numattnums; i < numattrs; i++)
625 {
626 Node *expr = list_nth(exprs, i - numattnums);
627
628 atttypids[i] = exprType(expr);
629 atttypmods[i] = exprTypmod(expr);
630 atttypcolls[i] = exprCollation(expr);
631 }
632 }
633
634 /*
635 * Populate the pg_statistic_ext_data result tuple.
636 */
637
638 /* Primary Key: cannot be NULL or replaced. */
640 nulls[Anum_pg_statistic_ext_data_stxoid - 1] = false;
643
644 /* All unspecified parameters will be left unmodified */
647 nulls[Anum_pg_statistic_ext_data_stxdmcv - 1] = true;
648 nulls[Anum_pg_statistic_ext_data_stxdexpr - 1] = true;
649
650 /*
651 * For each stats kind, deserialize the data at hand and perform a round
652 * of validation. The resulting tuple is filled with a set of updated
653 * values.
654 */
655
656 if (has.ndistinct)
657 {
661
662 if (statext_ndistinct_validate(ndistinct, &stxform->stxkeys,
664 {
668 }
669 else
670 success = false;
671
672 statext_ndistinct_free(ndistinct);
673 }
674
675 if (has.dependencies)
676 {
680
681 if (statext_dependencies_validate(dependencies, &stxform->stxkeys,
683 {
687 }
688 else
689 success = false;
690
691 statext_dependencies_free(dependencies);
692 }
693
694 if (has.mcv)
695 {
696 Datum datum;
697 bool val_ok = false;
698
702 atttypids, atttypmods, atttypcolls, numattrs,
703 &val_ok);
704
705 if (val_ok)
706 {
707 Assert(datum != (Datum) 0);
709 nulls[Anum_pg_statistic_ext_data_stxdmcv - 1] = false;
711 }
712 else
713 success = false;
714 }
715
716 if (has.expressions)
717 {
718 Datum datum;
720 bool ok = false;
721
723
724 /*
725 * Generate the expressions array.
726 *
727 * The attytypids, attytypmods, and atttypcolls arrays have all the
728 * regular attributes listed first, so we can pass those arrays with a
729 * start point after the last regular attribute. There are numexprs
730 * elements remaining.
731 */
734 &atttypmods[numattnums],
737 &ok);
738
740
741 if (ok)
742 {
743 Assert(datum != (Datum) 0);
746 nulls[Anum_pg_statistic_ext_data_stxdexpr - 1] = false;
747 }
748 else
749 success = false;
750 }
751
753
754cleanup:
757 if (pg_stext != NULL)
759 if (atttypids != NULL)
761 if (atttypmods != NULL)
762 pfree(atttypmods);
763 if (atttypcolls != NULL)
765 return success;
766}
767
768/*
769 * Consistency checks to ensure that other mcvlist arrays are in alignment
770 * with the mcv array.
771 */
772static bool
773check_mcvlist_array(const ArrayType *arr, int argindex, int required_ndims,
774 int mcv_length)
775{
776 if (ARR_NDIM(arr) != required_ndims)
777 {
780 errmsg("could not parse array \"%s\": incorrect number of dimensions (%d required)",
781 extarginfo[argindex].argname, required_ndims));
782 return false;
783 }
784
785 if (array_contains_nulls(arr))
786 {
789 errmsg("could not parse array \"%s\": NULL value found",
790 extarginfo[argindex].argname));
791 return false;
792 }
793
794 if (ARR_DIMS(arr)[0] != mcv_length)
795 {
798 errmsg("could not parse array \"%s\": incorrect number of elements (same as \"%s\" required)",
799 extarginfo[argindex].argname,
801 return false;
802 }
803
804 return true;
805}
806
807/*
808 * Create the stxdmcv datum from the equal-sized arrays of most common values,
809 * their null flags, and the frequency and base frequency associated with
810 * each value.
811 */
812static Datum
814 const ArrayType *base_freqs_arr, Oid *atttypids, int32 *atttypmods,
815 Oid *atttypcolls, int numattrs, bool *ok)
816{
817 int nitems;
819 bool *mcv_nulls;
820 int check_nummcv;
821 Datum mcv = (Datum) 0;
822
823 *ok = false;
824
825 /*
826 * mcv_arr is an array of arrays. Each inner array must have the same
827 * number of elements "numattrs".
828 */
829 if (ARR_NDIM(mcv_arr) != 2)
830 {
833 errmsg("could not parse array \"%s\": incorrect number of dimensions (%d required)",
835 goto mcv_error;
836 }
837
838 if (ARR_DIMS(mcv_arr)[1] != numattrs)
839 {
842 errmsg("could not parse array \"%s\": found %d attributes but expected %d",
845 goto mcv_error;
846 }
847
848 /*
849 * "most_common_freqs" and "most_common_base_freqs" arrays must be of the
850 * same length, one-dimension and cannot contain NULLs. We use mcv_arr as
851 * the reference array for determining their length.
852 */
853 nitems = ARR_DIMS(mcv_arr)[0];
856 {
857 /* inconsistent input arrays found */
858 goto mcv_error;
859 }
860
861 /*
862 * This part builds the contents for "most_common_val_nulls", based on the
863 * values from "most_common_vals".
864 */
867
869 atttypids, atttypmods, atttypcolls,
873
874 *ok = (mcv != (Datum) 0);
875
877 return mcv;
878}
879
880/*
881 * Check if key is found in the list of expression argnames.
882 */
883static bool
885{
886 Assert(key->type == jbvString);
887 for (int i = 0; i < NUM_ATTRIBUTE_STATS_ELEMS; i++)
888 {
889 if (strncmp(extexprargname[i], key->val.string.val, key->val.string.len) == 0)
890 return true;
891 }
892 return false;
893}
894
895/*
896 * Verify that all of the keys in the object are valid argnames.
897 */
898static bool
900{
901 bool all_keys_valid = true;
902
906
908
910
911 /* We always start off with a BEGIN OBJECT */
912 jitok = JsonbIteratorNext(&jbit, &jkey, false);
914
915 while (true)
916 {
918
919 jitok = JsonbIteratorNext(&jbit, &jkey, false);
920
921 /*
922 * We have run of keys. This is the only condition where it is
923 * memory-safe to break out of the loop.
924 */
925 if (jitok == WJB_END_OBJECT)
926 break;
927
928 /* We can only find keys inside an object */
929 Assert(jitok == WJB_KEY);
930 Assert(jkey.type == jbvString);
931
932 /* A value must follow the key */
933 jitok = JsonbIteratorNext(&jbit, &jval, false);
935
936 /*
937 * If we have already found an invalid key, there is no point in
938 * looking for more, because additional WARNINGs are just clutter. We
939 * must continue iterating over the json to ensure that we clean up
940 * all allocated memory.
941 */
942 if (!all_keys_valid)
943 continue;
944
946 {
948
951 errmsg("could not import element in expression %d: invalid key name",
952 exprnum));
953
955 all_keys_valid = false;
956 }
957 }
958 return all_keys_valid;
959}
960
961/*
962 * Simple conversion of jbvString to cstring
963 */
964static char *
966{
967 char *s;
968
969 Assert(jval->type == jbvString);
970
971 s = palloc0(jval->val.string.len + 1);
972 memcpy(s, jval->val.string.val, jval->val.string.len);
973
974 return s;
975}
976
977/*
978 * Apply a jbvString value to a safe scalar input function.
979 */
980static bool
982 const char *argname, Datum *datum)
983{
984 ErrorSaveContext escontext = {
986 .details_wanted = true
987 };
988
989 char *s = jbv_string_get_cstr(jval);
990 bool ok;
991
993 (Node *) &escontext, datum);
994
995 /*
996 * If we got a type import error, use the report generated and add an
997 * error hint before throwing a warning.
998 */
999 if (!ok)
1000 {
1002
1005 "Element \"%s\" in expression %d could not be parsed.",
1006 argname, exprnum);
1007
1008 escontext.error_data->elevel = WARNING;
1009 escontext.error_data->hint = hint_str.data;
1010
1011 ThrowErrorData(escontext.error_data);
1012 pfree(hint_str.data);
1013 }
1014
1015 pfree(s);
1016 return ok;
1017}
1018
1019/*
1020 * Build an array datum with element type elemtypid from a text datum, used as
1021 * value of an attribute in a pg_statistic tuple.
1022 *
1023 * If an error is encountered, capture it, and reduce the elevel to WARNING.
1024 *
1025 * This is an adaptation of statatt_build_stavalues().
1026 */
1027static Datum
1028array_in_safe(FmgrInfo *array_in, const char *s, Oid typid, int32 typmod,
1029 AttrNumber exprnum, const char *element_name, bool *ok)
1030{
1031 LOCAL_FCINFO(fcinfo, 3);
1032 Datum result;
1033
1034 ErrorSaveContext escontext = {
1036 .details_wanted = true
1037 };
1038
1039 *ok = false;
1041 (Node *) &escontext, NULL);
1042
1043 fcinfo->args[0].value = CStringGetDatum(s);
1044 fcinfo->args[0].isnull = false;
1045 fcinfo->args[1].value = ObjectIdGetDatum(typid);
1046 fcinfo->args[1].isnull = false;
1047 fcinfo->args[2].value = Int32GetDatum(typmod);
1048 fcinfo->args[2].isnull = false;
1049
1050 result = FunctionCallInvoke(fcinfo);
1051
1052 /*
1053 * If the array_in function returned an error, we will want to report that
1054 * ERROR as a WARNING, and add some location context to the error message.
1055 * Overwriting the existing hint (if any) is not ideal, and an error
1056 * context would only work for level >= ERROR.
1057 */
1058 if (escontext.error_occurred)
1059 {
1061
1064 "Element \"%s\" in expression %d could not be parsed.",
1066 escontext.error_data->elevel = WARNING;
1067 escontext.error_data->hint = hint_str.data;
1068 ThrowErrorData(escontext.error_data);
1069 pfree(hint_str.data);
1070 return (Datum) 0;
1071 }
1072
1074 {
1077 errmsg("could not import element \"%s\" in expression %d: null value found",
1079 return (Datum) 0;
1080 }
1081
1082 *ok = true;
1083 return result;
1084}
1085
1086/*
1087 * Create a pg_statistic tuple from an expression JSONB container.
1088 *
1089 * The pg_statistic tuple is pre-populated with acceptable defaults, therefore
1090 * even if there is an issue with all of the keys in the container, we can
1091 * still return a legit tuple datum.
1092 *
1093 * Set pg_statistic_ok to true if all of the values found in the container
1094 * were imported without issue. pg_statistic_ok is swicthed to "true" once
1095 * the full pg_statistic tuple has been built and validated.
1096 */
1097static Datum
1100 Oid typid, int32 typmod, Oid typcoll,
1101 bool *pg_statistic_ok)
1102{
1104 TypeCacheEntry *typcache;
1106 bool nulls[Natts_pg_statistic];
1109 Datum pgstdat = (Datum) 0;
1112 bool found[NUM_ATTRIBUTE_STATS_ELEMS] = {0};
1114
1115 /* Assume the worst by default. */
1116 *pg_statistic_ok = false;
1117
1119 {
1122 errmsg("could not parse \"%s\": invalid element in expression %d",
1123 argname, exprnum));
1124 goto pg_statistic_error;
1125 }
1126
1127 /*
1128 * Loop through all keys that we need to look up. If any value found is
1129 * neither a string nor a NULL, there is not much we can do, so just give
1130 * on the entire tuple for this expression.
1131 */
1132 for (int i = 0; i < NUM_ATTRIBUTE_STATS_ELEMS; i++)
1133 {
1134 const char *s = extexprargname[i];
1135 int len = strlen(s);
1136
1138 continue;
1139
1140 switch (val[i].type)
1141 {
1142 case jbvString:
1143 found[i] = true;
1144 break;
1145
1146 case jbvNull:
1147 break;
1148
1149 default:
1152 errmsg("could not parse \"%s\": invalid element in expression %d", argname, exprnum),
1153 errhint("Value of element \"%s\" must be type a null or a string.", s));
1154 goto pg_statistic_error;
1155 }
1156 }
1157
1158 /* Look for invalid keys */
1160 goto pg_statistic_error;
1161
1162 /*
1163 * There are two arg pairs, MCV+MCF and MCEV+MCEF. Both values must
1164 * either be found or not be found. Any disagreement is a warning. Once
1165 * we have ruled out disagreeing pairs, we can use either found flag as a
1166 * proxy for the other.
1167 */
1168 if (found[MOST_COMMON_VALS_ELEM] != found[MOST_COMMON_FREQS_ELEM])
1169 {
1172 errmsg("could not parse \"%s\": invalid element in expression %d",
1173 argname, exprnum),
1174 errhint("\"%s\" and \"%s\" must be both either strings or nulls.",
1177 goto pg_statistic_error;
1178 }
1180 {
1183 errmsg("could not parse \"%s\": invalid element in expression %d",
1184 argname, exprnum),
1185 errhint("\"%s\" and \"%s\" must be both either strings or nulls.",
1188 goto pg_statistic_error;
1189 }
1190
1191 /*
1192 * Range types may expect three values to be set. All three of them must
1193 * either be found or not be found. Any disagreement is a warning.
1194 */
1197 {
1200 errmsg("could not parse \"%s\": invalid element in expression %d",
1201 argname, exprnum),
1202 errhint("\"%s\", \"%s\", and \"%s\" must be all either strings or all nulls.",
1206 goto pg_statistic_error;
1207 }
1208
1209 /* This finds the right operators even if atttypid is a domain */
1211
1213 values, nulls, replaces);
1214
1215 /*
1216 * Special case: collation for tsvector is DEFAULT_COLLATION_OID. See
1217 * compute_tsvector_stats().
1218 */
1219 if (typid == TSVECTOROID)
1221
1222 /*
1223 * We only need to fetch element type and eq operator if we have a stat of
1224 * type MCELEM or DECHIST, otherwise the values are unnecessary and not
1225 * meaningful.
1226 */
1228 {
1229 if (!statatt_get_elem_type(typid, typcache->typtype,
1230 &elemtypid, &elemeqopr))
1231 {
1234 errmsg("could not parse \"%s\": invalid element type in expression %d",
1235 argname, exprnum));
1236 goto pg_statistic_error;
1237 }
1238 }
1239
1240 /*
1241 * These three fields can only be set if dealing with a range or
1242 * multi-range type.
1243 */
1244 if (found[RANGE_LENGTH_HISTOGRAM_ELEM] ||
1245 found[RANGE_EMPTY_FRAC_ELEM] ||
1247 {
1248 if (typcache->typtype != TYPTYPE_RANGE &&
1249 typcache->typtype != TYPTYPE_MULTIRANGE)
1250 {
1253 errmsg("could not parse \"%s\": invalid data in expression %d",
1254 argname, exprnum),
1255 errhint("\"%s\", \"%s\", and \"%s\" can only be set for a range type.",
1259 goto pg_statistic_error;
1260 }
1261 }
1262
1263 /* null_frac */
1264 if (found[NULL_FRAC_ELEM])
1265 {
1266 Datum datum;
1267
1271 else
1272 goto pg_statistic_error;
1273 }
1274
1275 /* avg_width */
1276 if (found[AVG_WIDTH_ELEM])
1277 {
1278 Datum datum;
1279
1283 else
1284 goto pg_statistic_error;
1285 }
1286
1287 /* n_distinct */
1288 if (found[N_DISTINCT_ELEM])
1289 {
1290 Datum datum;
1291
1295 else
1296 goto pg_statistic_error;
1297 }
1298
1299 /*
1300 * The STAKIND statistics are the same as the ones found in attribute
1301 * stats. However, these are all derived from json strings, whereas the
1302 * ones derived for attribute stats are a mix of datatypes. This limits
1303 * the opportunities for code sharing between the two.
1304 *
1305 * Some statistic kinds have both a stanumbers and a stavalues components.
1306 * In those cases, both values must either be NOT NULL or both NULL, and
1307 * if they aren't then we need to reject that stakind completely.
1308 * Currently we go a step further and reject the expression array
1309 * completely.
1310 *
1311 * Once it is established that the pairs are in NULL/NOT-NULL alignment,
1312 * we can test either expr_nulls[] value to see if the stakind has
1313 * value(s) that we can set or not.
1314 */
1315
1316 if (found[MOST_COMMON_VALS_ELEM])
1317 {
1318 Datum stavalues;
1319 Datum stanumbers;
1320 bool val_ok = false;
1321 bool num_ok = false;
1322 char *s;
1323
1325 stavalues = array_in_safe(array_in_fn, s, typid, typmod, exprnum,
1327 &val_ok);
1328
1329 pfree(s);
1330
1332 stanumbers = array_in_safe(array_in_fn, s, FLOAT4OID, -1, exprnum,
1334 &num_ok);
1335 pfree(s);
1336
1337 /* Only set the slot if both datums have been built */
1338 if (val_ok && num_ok)
1341 typcache->eq_opr, typcoll,
1342 stanumbers, false, stavalues, false);
1343 else
1344 goto pg_statistic_error;
1345 }
1346
1347 /* STATISTIC_KIND_HISTOGRAM */
1348 if (found[HISTOGRAM_BOUNDS_ELEM])
1349 {
1350 Datum stavalues;
1351 bool val_ok = false;
1353
1354 stavalues = array_in_safe(array_in_fn, s, typid, typmod, exprnum,
1356 &val_ok);
1357 pfree(s);
1358
1359 if (val_ok)
1362 typcache->lt_opr, typcoll,
1363 0, true, stavalues, false);
1364 else
1365 goto pg_statistic_error;
1366 }
1367
1368 /* STATISTIC_KIND_CORRELATION */
1369 if (found[CORRELATION_ELEM])
1370 {
1371 Datum corr[] = {(Datum) 0};
1372
1375 {
1377 Datum stanumbers = PointerGetDatum(arry);
1378
1381 typcache->lt_opr, typcoll,
1382 stanumbers, false, 0, true);
1383 }
1384 else
1385 goto pg_statistic_error;
1386 }
1387
1388 /* STATISTIC_KIND_MCELEM */
1389 if (found[MOST_COMMON_ELEMS_ELEM])
1390 {
1391 Datum stavalues;
1392 Datum stanumbers;
1393 bool val_ok = false;
1394 bool num_ok = false;
1395 char *s;
1396
1398 stavalues = array_in_safe(array_in_fn, s, elemtypid, typmod, exprnum,
1400 &val_ok);
1401 pfree(s);
1402
1403
1405 stanumbers = array_in_safe(array_in_fn, s, FLOAT4OID, -1, exprnum,
1407 &num_ok);
1408 pfree(s);
1409
1410 /* Only set the slot if both datums have been built */
1411 if (val_ok && num_ok)
1415 stanumbers, false, stavalues, false);
1416 else
1417 goto pg_statistic_error;
1418 }
1419
1420 /* STATISTIC_KIND_DECHIST */
1421 if (found[ELEM_COUNT_HISTOGRAM_ELEM])
1422 {
1423 Datum stanumbers;
1424 bool num_ok = false;
1425 char *s;
1426
1428 stanumbers = array_in_safe(array_in_fn, s, FLOAT4OID, -1, exprnum,
1430 &num_ok);
1431 pfree(s);
1432
1433 if (num_ok)
1435 elemeqopr, typcoll, stanumbers, false, 0, true);
1436 else
1437 goto pg_statistic_error;
1438 }
1439
1440 /*
1441 * STATISTIC_KIND_BOUNDS_HISTOGRAM
1442 *
1443 * This stakind appears before STATISTIC_KIND_RANGE_LENGTH_HISTOGRAM even
1444 * though it is numerically greater, and all other stakinds appear in
1445 * numerical order.
1446 */
1447 if (found[RANGE_BOUNDS_HISTOGRAM_ELEM])
1448 {
1449 Datum stavalues;
1450 bool val_ok = false;
1451 char *s;
1452 Oid rtypid = typid;
1453
1454 /*
1455 * If it's a multirange, step down to the range type, as is done by
1456 * multirange_typanalyze().
1457 */
1458 if (type_is_multirange(typid))
1460
1462
1463 stavalues = array_in_safe(array_in_fn, s, rtypid, typmod, exprnum,
1465 &val_ok);
1466
1467 if (val_ok)
1471 0, true, stavalues, false);
1472 else
1473 goto pg_statistic_error;
1474 }
1475
1476 /* STATISTIC_KIND_RANGE_LENGTH_HISTOGRAM */
1477 if (found[RANGE_LENGTH_HISTOGRAM_ELEM])
1478 {
1479 Datum empty_frac[] = {(Datum) 0};
1480 Datum stavalues;
1481 Datum stanumbers;
1482 bool val_ok = false;
1483 char *s;
1484
1487 {
1489
1490 stanumbers = PointerGetDatum(arry);
1491 }
1492 else
1493 goto pg_statistic_error;
1494
1496 stavalues = array_in_safe(array_in_fn, s, FLOAT8OID, -1, exprnum,
1498 &val_ok);
1499
1500 if (val_ok)
1504 stanumbers, false, stavalues, false);
1505 else
1506 goto pg_statistic_error;
1507 }
1508
1511
1513
1514 *pg_statistic_ok = true;
1515
1516 return pgstdat;
1517
1519 return (Datum) 0;
1520}
1521
1522/*
1523 * Create the stxdexpr datum, which is an array of pg_statistic rows with all
1524 * of the object identification fields left at defaults, using the json array
1525 * of objects/nulls referenced against the datatypes for the expressions.
1526 *
1527 * The exprs_is_perfect will be set to true if all pg_statistic rows were
1528 * imported cleanly. If any of them experienced a problem (and thus were
1529 * set as if they were null), then the expression is kept but exprs_is_perfect
1530 * will be marked as false.
1531 *
1532 * This datum is needed to fill out a complete pg_statistic_ext_data tuple.
1533 */
1534static Datum
1536 Oid *atttypids, int32 *atttypmods,
1538 bool *exprs_is_perfect)
1539{
1542 ArrayBuildState *astate = NULL;
1543 Datum result = (Datum) 0;
1544 int num_import_ok = 0;
1547
1549
1550 *exprs_is_perfect = false;
1551
1552 /* Json schema must be [{expr},...] */
1554 {
1557 errmsg("could not parse \"%s\": root-level array required", argname));
1558 goto exprs_error;
1559 }
1560
1561 root = &exprs_jsonb->root;
1562
1563 /*
1564 * The number of elements in the array must match the number of
1565 * expressions in the stats object definition.
1566 */
1569 {
1572 errmsg("could not parse \"%s\": incorrect number of elements (%d required)",
1574 goto exprs_error;
1575 }
1576
1578
1579 /*
1580 * Iterate over each expected expression object in the array. Some of
1581 * them could be null. If the element is a completely wrong data type,
1582 * give a WARNING and then treat the element like a NULL element in the
1583 * result array.
1584 *
1585 * Each expression *MUST* have a value appended in the result pg_statistic
1586 * array.
1587 */
1588 for (int i = 0; i < numexprs; i++)
1589 {
1590 Datum pgstdat = (Datum) 0;
1591 bool isnull = false;
1592 AttrNumber exprattnum = -1 - i;
1593
1595
1596 switch (elem->type)
1597 {
1598 case jbvBinary:
1599 {
1600 bool sta_ok = false;
1601
1602 /* a real stats object */
1603 pgstdat = import_pg_statistic(pgsd, elem->val.binary.data,
1605 atttypids[i], atttypmods[i],
1606 atttypcolls[i], &sta_ok);
1607
1608 /*
1609 * If some incorrect data has been found, assign NULL for
1610 * this expression as a mean to give up.
1611 */
1612 if (sta_ok)
1613 num_import_ok++;
1614 else
1615 {
1616 isnull = true;
1617 pgstdat = (Datum) 0;
1618 }
1619 }
1620 break;
1621
1622 case jbvNull:
1623 /* NULL placeholder for invalid data, still fine */
1624 isnull = true;
1625 num_import_ok++;
1626 break;
1627
1628 default:
1629 /* cannot possibly be valid */
1632 errmsg("could not parse \"%s\": invalid element in expression %d",
1634 goto exprs_error;
1635 }
1636
1637 astate = accumArrayResult(astate, pgstdat, isnull, pgstypoid,
1639 }
1640
1641 /*
1642 * The expressions datum is perfect *if and only if* all of the
1643 * pg_statistic elements were also ok, for a number of elements equal to
1644 * the number of expressions. Anything else means a failure in restoring
1645 * the data of this statistics object.
1646 */
1648
1649 if (astate != NULL)
1650 result = makeArrayResult(astate, CurrentMemoryContext);
1651
1652 return result;
1653
1655 if (astate != NULL)
1656 pfree(astate);
1657 return (Datum) 0;
1658};
1659
1660/*
1661 * Remove an existing pg_statistic_ext_data row for a given pg_statistic_ext
1662 * row and "inherited" pair.
1663 */
1664static bool
1666{
1669 bool result = false;
1670
1671 /* Is there already a pg_statistic_ext_data tuple for this attribute? */
1675
1677 {
1678 CatalogTupleDelete(sed, &oldtup->t_self);
1680 result = true;
1681 }
1682
1684
1686
1687 return result;
1688}
1689
1690/*
1691 * Restore (insert or replace) statistics for the given statistics object.
1692 *
1693 * This function accepts variadic arguments in key-value pairs, which are
1694 * given to stats_fill_fcinfo_from_arg_pairs to be mapped into positional
1695 * arguments.
1696 */
1697Datum
1714
1715/*
1716 * Delete statistics for the given statistics object.
1717 */
1718Datum
1720{
1721 char *relnspname;
1722 char *relname;
1723 char *nspname;
1724 Oid nspoid;
1725 Oid relid;
1726 char *stxname;
1727 bool inherited;
1729 HeapTuple tup;
1732
1733 /* relation arguments */
1738
1739 /* extended statistics arguments */
1746
1747 if (RecoveryInProgress())
1748 {
1751 errmsg("recovery is in progress"),
1752 errhint("Statistics cannot be modified during recovery."));
1754 }
1755
1756 /*
1757 * First open the relation where we expect to find the statistics. This
1758 * is similar to relation and attribute statistics, so as ACL checks are
1759 * done before any locks are taken, even before any attempts related to
1760 * the extended stats object.
1761 */
1765
1766 /* Now check if the namespace of the stats object exists. */
1767 nspoid = get_namespace_oid(nspname, true);
1768 if (nspoid == InvalidOid)
1769 {
1772 errmsg("could not find schema \"%s\"", nspname));
1774 }
1775
1778
1779 if (!HeapTupleIsValid(tup))
1780 {
1784 errmsg("could not find extended statistics object \"%s.%s\"",
1785 nspname, stxname));
1787 }
1788
1790
1791 /*
1792 * This should be consistent, based on the lock taken on the table when we
1793 * started.
1794 */
1795 if (stxform->stxrelid != relid)
1796 {
1800 errmsg("could not clear extended statistics object \"%s.%s\": incorrect relation \"%s.%s\" specified",
1804 }
1805
1808
1810
1812}
#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
ArrayBuildState * accumArrayResult(ArrayBuildState *astate, Datum dvalue, bool disnull, Oid element_type, MemoryContext rcontext)
bool array_contains_nulls(const ArrayType *array)
Datum array_in(PG_FUNCTION_ARGS)
Definition arrayfuncs.c:181
ArrayType * construct_array_builtin(Datum *elems, int nelems, Oid elmtype)
void deconstruct_array_builtin(const ArrayType *array, Oid elmtype, Datum **elemsp, bool **nullsp, int *nelemsp)
Datum makeArrayResult(ArrayBuildState *astate, MemoryContext rcontext)
int16 AttrNumber
Definition attnum.h:21
#define InvalidAttrNumber
Definition attnum.h:23
static Datum values[MAXATTR]
Definition bootstrap.c:188
static void cleanup(void)
Definition bootstrap.c:879
#define TextDatumGetCString(d)
Definition builtins.h:99
#define Assert(condition)
Definition c.h:945
double float8
Definition c.h:716
int32_t int32
Definition c.h:614
#define OidIsValid(objectId)
Definition c.h:860
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition clauses.c:2498
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)
void ThrowErrorData(ErrorData *edata)
Definition elog.c:2090
int errcode(int sqlerrcode)
Definition elog.c:874
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
static bool key_in_expr_argnames(JsonbValue *key)
extended_stats_argnum
@ INHERITED_ARG
@ EXPRESSIONS_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 Datum import_expressions(Relation pgsd, int numexprs, Oid *atttypids, int32 *atttypmods, Oid *atttypcolls, Jsonb *exprs_jsonb, bool *exprs_is_perfect)
static bool delete_pg_statistic_ext_data(Oid stxoid, bool inherited)
static struct StatsArgInfo extarginfo[]
Datum pg_restore_extended_stats(PG_FUNCTION_ARGS)
extended_stats_exprs_element
@ MOST_COMMON_ELEM_FREQS_ELEM
@ NUM_ATTRIBUTE_STATS_ELEMS
@ RANGE_EMPTY_FRAC_ELEM
@ N_DISTINCT_ELEM
@ AVG_WIDTH_ELEM
@ ELEM_COUNT_HISTOGRAM_ELEM
@ HISTOGRAM_BOUNDS_ELEM
@ MOST_COMMON_FREQS_ELEM
@ CORRELATION_ELEM
@ RANGE_LENGTH_HISTOGRAM_ELEM
@ MOST_COMMON_VALS_ELEM
@ RANGE_BOUNDS_HISTOGRAM_ELEM
@ NULL_FRAC_ELEM
@ MOST_COMMON_ELEMS_ELEM
static bool jbv_to_infunc_datum(JsonbValue *jval, PGFunction func, AttrNumber exprnum, const char *argname, Datum *datum)
static Datum import_pg_statistic(Relation pgsd, JsonbContainer *cont, AttrNumber exprnum, FmgrInfo *array_in_fn, Oid typid, int32 typmod, Oid typcoll, bool *pg_statistic_ok)
static void expand_stxkind(HeapTuple tup, StakindFlags *enabled)
static char * jbv_string_get_cstr(JsonbValue *jval)
static HeapTuple get_pg_statistic_ext(Relation pg_stext, Oid nspoid, const char *stxname)
static Datum array_in_safe(FmgrInfo *array_in, const char *s, Oid typid, int32 typmod, AttrNumber exprnum, const char *element_name, bool *ok)
static bool extended_statistics_update(FunctionCallInfo fcinfo)
static bool check_all_expr_argnames_valid(JsonbContainer *cont, AttrNumber exprnum)
static const char * extexprargname[NUM_ATTRIBUTE_STATS_ELEMS]
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
Datum float4in(PG_FUNCTION_ARGS)
Definition float.c:181
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition fmgr.c:129
bool DirectInputFunctionCallSafe(PGFunction func, char *str, Oid typioparam, int32 typmod, Node *escontext, Datum *result)
Definition fmgr.c:1641
#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 FunctionCallInvoke(fcinfo)
Definition fmgr.h:172
#define PG_GETARG_BOOL(n)
Definition fmgr.h:274
Datum(* PGFunction)(FunctionCallInfo fcinfo)
Definition fmgr.h:40
#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:1130
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
Definition heaptuple.c:1037
Datum heap_copy_tuple_as_datum(HeapTuple tuple, TupleDesc tupleDesc)
Definition heaptuple.c:1001
void heap_freetuple(HeapTuple htup)
Definition heaptuple.c:1384
#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
long val
Definition informix.c:689
static bool success
Definition initdb.c:188
Datum int4in(PG_FUNCTION_ARGS)
Definition int.c:316
int i
Definition isn.c:77
@ jbvBinary
Definition jsonb.h:238
@ jbvNull
Definition jsonb.h:230
@ jbvString
Definition jsonb.h:231
#define JsonContainerSize(jc)
Definition jsonb.h:208
#define JB_ROOT_IS_ARRAY(jbp_)
Definition jsonb.h:224
#define PG_GETARG_JSONB_P(x)
Definition jsonb.h:418
#define JsonContainerIsObject(jc)
Definition jsonb.h:210
JsonbIteratorToken
Definition jsonb.h:21
@ WJB_KEY
Definition jsonb.h:23
@ WJB_VALUE
Definition jsonb.h:24
@ WJB_END_OBJECT
Definition jsonb.h:29
@ WJB_BEGIN_OBJECT
Definition jsonb.h:28
JsonbValue * getKeyJsonValueFromContainer(JsonbContainer *container, const char *keyVal, int keyLen, JsonbValue *res)
Definition jsonb_util.c:402
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition jsonb_util.c:935
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition jsonb_util.c:973
JsonbValue * getIthJsonbValueFromContainer(JsonbContainer *container, uint32 i)
Definition jsonb_util.c:472
#define ShareUpdateExclusiveLock
Definition lockdefs.h:39
#define RowExclusiveLock
Definition lockdefs.h:38
Oid get_multirange_range(Oid multirangeOid)
Definition lsyscache.c:3705
Oid get_rel_type_id(Oid relid)
Definition lsyscache.c:2199
char * get_namespace_name(Oid nspid)
Definition lsyscache.c:3588
bool type_is_multirange(Oid typid)
Definition lsyscache.c:2920
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 * palloc0(Size size)
Definition mcxt.c:1417
MemoryContext CurrentMemoryContext
Definition mcxt.c:160
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:304
Oid exprCollation(const Node *expr)
Definition nodeFuncs.c:826
void fix_opfuncids(Node *node)
Definition nodeFuncs.c:1848
static char * errmsg
int16 attnum
FormData_pg_attribute * Form_pg_attribute
NameData relname
Definition pg_class.h:40
const void size_t len
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 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
uint64_t Datum
Definition postgres.h:70
static Datum CStringGetDatum(const char *X)
Definition postgres.h:370
static Datum Int32GetDatum(int32 X)
Definition postgres.h:212
#define InvalidOid
unsigned int Oid
static int fb(int x)
tree ctl root
Definition radixtree.h:1857
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 statatt_get_elem_type(Oid atttypid, char atttyptype, Oid *elemtypid, Oid *elem_eq_opr)
Definition stat_utils.c:523
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 statatt_init_empty_tuple(Oid reloid, int16 attnum, bool inherited, Datum *values, bool *nulls, bool *replaces)
Definition stat_utils.c:713
void stats_check_required_arg(FunctionCallInfo fcinfo, struct StatsArgInfo *arginfo, int argnum)
Definition stat_utils.c:51
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
#define BTEqualStrategyNumber
Definition stratnum.h:31
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition stringinfo.c:145
void initStringInfo(StringInfo str)
Definition stringinfo.c:97
int elevel
Definition elog.h:421
char * hint
Definition elog.h:435
ErrorData * error_data
Definition miscnodes.h:49
enum jbvType type
Definition jsonb.h:257
char * val
Definition jsonb.h:266
Definition jsonb.h:215
Definition pg_list.h:54
Definition nodes.h:135
const char * argname
Definition stat_utils.h:24
Definition c.h:778
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
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition typcache.c:389
#define TYPECACHE_EQ_OPR
Definition typcache.h:138
#define TYPECACHE_LT_OPR
Definition typcache.h:139
const char * type
void CommandCounterIncrement(void)
Definition xact.c:1102
bool RecoveryInProgress(void)
Definition xlog.c:6444
static zic_t corr[TZ_MAX_LEAPS]
Definition zic.c:406