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 * VacAttrStatsP 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 AttrNumber order, but we do not
590 * rely 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 atttypids, atttypmods, 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 switched 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
1312 if (found[MOST_COMMON_VALS_ELEM])
1313 {
1314 Datum stavalues;
1315 Datum stanumbers;
1316 bool val_ok = false;
1317 bool num_ok = false;
1318 char *s;
1319
1321 stavalues = array_in_safe(array_in_fn, s, typid, typmod, exprnum,
1323 &val_ok);
1324
1325 pfree(s);
1326
1328 stanumbers = array_in_safe(array_in_fn, s, FLOAT4OID, -1, exprnum,
1330 &num_ok);
1331 pfree(s);
1332
1333 /* Only set the slot if both datums have been built */
1334 if (val_ok && num_ok)
1337 typcache->eq_opr, typcoll,
1338 stanumbers, false, stavalues, false);
1339 else
1340 goto pg_statistic_error;
1341 }
1342
1343 /* STATISTIC_KIND_HISTOGRAM */
1344 if (found[HISTOGRAM_BOUNDS_ELEM])
1345 {
1346 Datum stavalues;
1347 bool val_ok = false;
1349
1350 stavalues = array_in_safe(array_in_fn, s, typid, typmod, exprnum,
1352 &val_ok);
1353 pfree(s);
1354
1355 if (val_ok)
1358 typcache->lt_opr, typcoll,
1359 0, true, stavalues, false);
1360 else
1361 goto pg_statistic_error;
1362 }
1363
1364 /* STATISTIC_KIND_CORRELATION */
1365 if (found[CORRELATION_ELEM])
1366 {
1367 Datum corr[] = {(Datum) 0};
1368
1371 {
1373 Datum stanumbers = PointerGetDatum(arry);
1374
1377 typcache->lt_opr, typcoll,
1378 stanumbers, false, 0, true);
1379 }
1380 else
1381 goto pg_statistic_error;
1382 }
1383
1384 /* STATISTIC_KIND_MCELEM */
1385 if (found[MOST_COMMON_ELEMS_ELEM])
1386 {
1387 Datum stavalues;
1388 Datum stanumbers;
1389 bool val_ok = false;
1390 bool num_ok = false;
1391 char *s;
1392
1394 stavalues = array_in_safe(array_in_fn, s, elemtypid, typmod, exprnum,
1396 &val_ok);
1397 pfree(s);
1398
1399
1401 stanumbers = array_in_safe(array_in_fn, s, FLOAT4OID, -1, exprnum,
1403 &num_ok);
1404 pfree(s);
1405
1406 /* Only set the slot if both datums have been built */
1407 if (val_ok && num_ok)
1411 stanumbers, false, stavalues, false);
1412 else
1413 goto pg_statistic_error;
1414 }
1415
1416 /* STATISTIC_KIND_DECHIST */
1417 if (found[ELEM_COUNT_HISTOGRAM_ELEM])
1418 {
1419 Datum stanumbers;
1420 bool num_ok = false;
1421 char *s;
1422
1424 stanumbers = array_in_safe(array_in_fn, s, FLOAT4OID, -1, exprnum,
1426 &num_ok);
1427 pfree(s);
1428
1429 if (num_ok)
1431 elemeqopr, typcoll, stanumbers, false, 0, true);
1432 else
1433 goto pg_statistic_error;
1434 }
1435
1436 /*
1437 * STATISTIC_KIND_BOUNDS_HISTOGRAM
1438 *
1439 * This stakind appears before STATISTIC_KIND_RANGE_LENGTH_HISTOGRAM even
1440 * though it is numerically greater, and all other stakinds appear in
1441 * numerical order.
1442 */
1443 if (found[RANGE_BOUNDS_HISTOGRAM_ELEM])
1444 {
1445 Datum stavalues;
1446 bool val_ok = false;
1447 char *s;
1448 Oid rtypid = typid;
1449
1450 /*
1451 * If it's a multirange, step down to the range type, as is done by
1452 * multirange_typanalyze().
1453 */
1454 if (type_is_multirange(typid))
1456
1458
1459 stavalues = array_in_safe(array_in_fn, s, rtypid, typmod, exprnum,
1461 &val_ok);
1462
1463 if (val_ok)
1467 0, true, stavalues, false);
1468 else
1469 goto pg_statistic_error;
1470 }
1471
1472 /* STATISTIC_KIND_RANGE_LENGTH_HISTOGRAM */
1473 if (found[RANGE_LENGTH_HISTOGRAM_ELEM])
1474 {
1475 Datum empty_frac[] = {(Datum) 0};
1476 Datum stavalues;
1477 Datum stanumbers;
1478 bool val_ok = false;
1479 char *s;
1480
1483 {
1485
1486 stanumbers = PointerGetDatum(arry);
1487 }
1488 else
1489 goto pg_statistic_error;
1490
1492 stavalues = array_in_safe(array_in_fn, s, FLOAT8OID, -1, exprnum,
1494 &val_ok);
1495
1496 if (val_ok)
1500 stanumbers, false, stavalues, false);
1501 else
1502 goto pg_statistic_error;
1503 }
1504
1507
1509
1510 *pg_statistic_ok = true;
1511
1512 return pgstdat;
1513
1515 return (Datum) 0;
1516}
1517
1518/*
1519 * Create the stxdexpr datum, which is an array of pg_statistic rows with all
1520 * of the object identification fields left at defaults, using the json array
1521 * of objects/nulls referenced against the datatypes for the expressions.
1522 *
1523 * The exprs_is_perfect will be set to true if all pg_statistic rows were
1524 * imported cleanly. If any of them experienced a problem (and thus were
1525 * set as if they were null), then the expression is kept but exprs_is_perfect
1526 * will be marked as false.
1527 *
1528 * This datum is needed to fill out a complete pg_statistic_ext_data tuple.
1529 */
1530static Datum
1532 Oid *atttypids, int32 *atttypmods,
1534 bool *exprs_is_perfect)
1535{
1538 ArrayBuildState *astate = NULL;
1539 Datum result = (Datum) 0;
1540 int num_import_ok = 0;
1543
1545
1546 *exprs_is_perfect = false;
1547
1548 /* Json schema must be [{expr},...] */
1550 {
1553 errmsg("could not parse \"%s\": root-level array required", argname));
1554 goto exprs_error;
1555 }
1556
1557 root = &exprs_jsonb->root;
1558
1559 /*
1560 * The number of elements in the array must match the number of
1561 * expressions in the stats object definition.
1562 */
1565 {
1568 errmsg("could not parse \"%s\": incorrect number of elements (%d required)",
1570 goto exprs_error;
1571 }
1572
1574
1575 /*
1576 * Iterate over each expected expression object in the array. Some of
1577 * them could be null. If the element is a completely wrong data type,
1578 * give a WARNING and then treat the element like a NULL element in the
1579 * result array.
1580 *
1581 * Each expression *MUST* have a value appended in the result pg_statistic
1582 * array.
1583 */
1584 for (int i = 0; i < numexprs; i++)
1585 {
1586 Datum pgstdat = (Datum) 0;
1587 bool isnull = false;
1588 AttrNumber exprattnum = -1 - i;
1589
1591
1592 switch (elem->type)
1593 {
1594 case jbvBinary:
1595 {
1596 bool sta_ok = false;
1597
1598 /* a real stats object */
1599 pgstdat = import_pg_statistic(pgsd, elem->val.binary.data,
1601 atttypids[i], atttypmods[i],
1602 atttypcolls[i], &sta_ok);
1603
1604 /*
1605 * If some incorrect data has been found, assign NULL for
1606 * this expression as a mean to give up.
1607 */
1608 if (sta_ok)
1609 num_import_ok++;
1610 else
1611 {
1612 isnull = true;
1613 pgstdat = (Datum) 0;
1614 }
1615 }
1616 break;
1617
1618 case jbvNull:
1619 /* NULL placeholder for invalid data, still fine */
1620 isnull = true;
1621 num_import_ok++;
1622 break;
1623
1624 default:
1625 /* cannot possibly be valid */
1628 errmsg("could not parse \"%s\": invalid element in expression %d",
1630 goto exprs_error;
1631 }
1632
1633 astate = accumArrayResult(astate, pgstdat, isnull, pgstypoid,
1635 }
1636
1637 /*
1638 * The expressions datum is perfect *if and only if* all of the
1639 * pg_statistic elements were also ok, for a number of elements equal to
1640 * the number of expressions. Anything else means a failure in restoring
1641 * the data of this statistics object.
1642 */
1644
1645 if (astate != NULL)
1647
1648 return result;
1649
1651 if (astate != NULL)
1652 pfree(astate);
1653 return (Datum) 0;
1654};
1655
1656/*
1657 * Remove an existing pg_statistic_ext_data row for a given pg_statistic_ext
1658 * row and "inherited" pair.
1659 */
1660static bool
1662{
1665 bool result = false;
1666
1667 /* Is there already a pg_statistic_ext_data tuple for this attribute? */
1671
1673 {
1674 CatalogTupleDelete(sed, &oldtup->t_self);
1676 result = true;
1677 }
1678
1680
1682
1683 return result;
1684}
1685
1686/*
1687 * Restore (insert or replace) statistics for the given statistics object.
1688 *
1689 * This function accepts variadic arguments in key-value pairs, which are
1690 * given to stats_fill_fcinfo_from_arg_pairs to be mapped into positional
1691 * arguments.
1692 */
1693Datum
1710
1711/*
1712 * Delete statistics for the given statistics object.
1713 */
1714Datum
1716{
1717 char *relnspname;
1718 char *relname;
1719 char *nspname;
1720 Oid nspoid;
1721 Oid relid;
1722 char *stxname;
1723 bool inherited;
1725 HeapTuple tup;
1728
1729 /* relation arguments */
1734
1735 /* extended statistics arguments */
1742
1743 if (RecoveryInProgress())
1744 {
1747 errmsg("recovery is in progress"),
1748 errhint("Statistics cannot be modified during recovery."));
1750 }
1751
1752 /*
1753 * First open the relation where we expect to find the statistics. This
1754 * is similar to relation and attribute statistics, so as ACL checks are
1755 * done before any locks are taken, even before any attempts related to
1756 * the extended stats object.
1757 */
1761
1762 /* Now check if the namespace of the stats object exists. */
1763 nspoid = get_namespace_oid(nspname, true);
1764 if (nspoid == InvalidOid)
1765 {
1768 errmsg("could not find schema \"%s\"", nspname));
1770 }
1771
1774
1775 if (!HeapTupleIsValid(tup))
1776 {
1780 errmsg("could not find extended statistics object \"%s.%s\"",
1781 nspname, stxname));
1783 }
1784
1786
1787 /*
1788 * This should be consistent, based on the lock taken on the table when we
1789 * started.
1790 */
1791 if (stxform->stxrelid != relid)
1792 {
1796 errmsg("could not clear extended statistics object \"%s.%s\": incorrect relation \"%s.%s\" specified",
1800 }
1801
1804
1806
1808}
#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:190
static void cleanup(void)
Definition bootstrap.c:886
#define TextDatumGetCString(d)
Definition builtins.h:99
#define Assert(condition)
Definition c.h:943
double float8
Definition c.h:714
int32_t int32
Definition c.h:620
#define OidIsValid(objectId)
Definition c.h:858
uint32 result
memcpy(sums, checksumBaseOffsets, sizeof(checksumBaseOffsets))
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition clauses.c:2500
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:2091
int errcode(int sqlerrcode)
Definition elog.c:875
int errhint(const char *fmt,...) pg_attribute_printf(1
#define WARNING
Definition elog.h:37
#define ERROR
Definition elog.h:40
#define elog(elevel,...)
Definition elog.h:228
#define ereport(elevel,...)
Definition elog.h:152
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:205
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:612
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition genam.c:523
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:1118
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
Definition heaptuple.c:1025
Datum heap_copy_tuple_as_datum(HeapTuple tuple, TupleDesc tupleDesc)
Definition heaptuple.c:989
void heap_freetuple(HeapTuple htup)
Definition heaptuple.c:1372
#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:3703
Oid get_rel_type_id(Oid relid)
Definition lsyscache.c:2172
char * get_namespace_name(Oid nspid)
Definition lsyscache.c:3561
bool type_is_multirange(Oid typid)
Definition lsyscache.c:2893
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:331
END_CATALOG_STRUCT typedef FormData_pg_statistic_ext * Form_pg_statistic_ext
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:383
static Datum Int32GetDatum(int32 X)
Definition postgres.h:212
#define PointerGetDatum(X)
Definition postgres.h:354
#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:542
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:423
char * hint
Definition elog.h:437
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:776
void ReleaseSysCache(HeapTuple tuple)
Definition syscache.c:265
HeapTuple SearchSysCache2(SysCacheIdentifier cacheId, Datum key1, Datum key2)
Definition syscache.c:231
Datum SysCacheGetAttrNotNull(SysCacheIdentifier cacheId, HeapTuple tup, AttrNumber attributeNumber)
Definition syscache.c:626
Datum SysCacheGetAttr(SysCacheIdentifier cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition syscache.c:596
#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:1130
bool RecoveryInProgress(void)
Definition xlog.c:6836
static zic_t corr[TZ_MAX_LEAPS]
Definition zic.c:406