PostgreSQL Source Code  git master
extended_stats.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * extended_stats.c
4  * POSTGRES extended statistics
5  *
6  * Generic code supporting statistics objects created via CREATE STATISTICS.
7  *
8  *
9  * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
10  * Portions Copyright (c) 1994, Regents of the University of California
11  *
12  * IDENTIFICATION
13  * src/backend/statistics/extended_stats.c
14  *
15  *-------------------------------------------------------------------------
16  */
17 #include "postgres.h"
18 
19 #include "access/genam.h"
20 #include "access/htup_details.h"
21 #include "access/table.h"
22 #include "access/tuptoaster.h"
23 #include "catalog/indexing.h"
24 #include "catalog/pg_collation.h"
27 #include "miscadmin.h"
28 #include "nodes/nodeFuncs.h"
29 #include "optimizer/clauses.h"
30 #include "optimizer/optimizer.h"
31 #include "postmaster/autovacuum.h"
33 #include "statistics/statistics.h"
34 #include "utils/array.h"
35 #include "utils/builtins.h"
36 #include "utils/fmgroids.h"
37 #include "utils/lsyscache.h"
38 #include "utils/memutils.h"
39 #include "utils/rel.h"
40 #include "utils/selfuncs.h"
41 #include "utils/syscache.h"
42 
43 /*
44  * To avoid consuming too much memory during analysis and/or too much space
45  * in the resulting pg_statistic rows, we ignore varlena datums that are wider
46  * than WIDTH_THRESHOLD (after detoasting!). This is legitimate for MCV
47  * and distinct-value calculations since a wide value is unlikely to be
48  * duplicated at all, much less be a most-common value. For the same reason,
49  * ignoring wide values will not affect our estimates of histogram bin
50  * boundaries very much.
51  */
52 #define WIDTH_THRESHOLD 1024
53 
54 /*
55  * Used internally to refer to an individual statistics object, i.e.,
56  * a pg_statistic_ext entry.
57  */
58 typedef struct StatExtEntry
59 {
60  Oid statOid; /* OID of pg_statistic_ext entry */
61  char *schema; /* statistics object's schema */
62  char *name; /* statistics object's name */
63  Bitmapset *columns; /* attribute numbers covered by the object */
64  List *types; /* 'char' list of enabled statistic kinds */
65 } StatExtEntry;
66 
67 
68 static List *fetch_statentries_for_relation(Relation pg_statext, Oid relid);
70  int nvacatts, VacAttrStats **vacatts);
71 static void statext_store(Oid relid,
72  MVNDistinct *ndistinct, MVDependencies *dependencies,
73  MCVList *mcv, VacAttrStats **stats);
74 
75 
76 /*
77  * Compute requested extended stats, using the rows sampled for the plain
78  * (single-column) stats.
79  *
80  * This fetches a list of stats types from pg_statistic_ext, computes the
81  * requested stats, and serializes them back into the catalog.
82  */
83 void
84 BuildRelationExtStatistics(Relation onerel, double totalrows,
85  int numrows, HeapTuple *rows,
86  int natts, VacAttrStats **vacattrstats)
87 {
88  Relation pg_stext;
89  ListCell *lc;
90  List *stats;
91  MemoryContext cxt;
92  MemoryContext oldcxt;
93 
95  "BuildRelationExtStatistics",
97  oldcxt = MemoryContextSwitchTo(cxt);
98 
99  pg_stext = table_open(StatisticExtRelationId, RowExclusiveLock);
100  stats = fetch_statentries_for_relation(pg_stext, RelationGetRelid(onerel));
101 
102  foreach(lc, stats)
103  {
105  MVNDistinct *ndistinct = NULL;
106  MVDependencies *dependencies = NULL;
107  MCVList *mcv = NULL;
108  VacAttrStats **stats;
109  ListCell *lc2;
110 
111  /*
112  * Check if we can build these stats based on the column analyzed. If
113  * not, report this fact (except in autovacuum) and move on.
114  */
115  stats = lookup_var_attr_stats(onerel, stat->columns,
116  natts, vacattrstats);
117  if (!stats)
118  {
121  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
122  errmsg("statistics object \"%s.%s\" could not be computed for relation \"%s.%s\"",
123  stat->schema, stat->name,
124  get_namespace_name(onerel->rd_rel->relnamespace),
125  RelationGetRelationName(onerel)),
126  errtable(onerel)));
127  continue;
128  }
129 
130  /* check allowed number of dimensions */
131  Assert(bms_num_members(stat->columns) >= 2 &&
133 
134  /* compute statistic of each requested type */
135  foreach(lc2, stat->types)
136  {
137  char t = (char) lfirst_int(lc2);
138 
139  if (t == STATS_EXT_NDISTINCT)
140  ndistinct = statext_ndistinct_build(totalrows, numrows, rows,
141  stat->columns, stats);
142  else if (t == STATS_EXT_DEPENDENCIES)
143  dependencies = statext_dependencies_build(numrows, rows,
144  stat->columns, stats);
145  else if (t == STATS_EXT_MCV)
146  mcv = statext_mcv_build(numrows, rows, stat->columns, stats,
147  totalrows);
148  }
149 
150  /* store the statistics in the catalog */
151  statext_store(stat->statOid, ndistinct, dependencies, mcv, stats);
152  }
153 
154  table_close(pg_stext, RowExclusiveLock);
155 
156  MemoryContextSwitchTo(oldcxt);
157  MemoryContextDelete(cxt);
158 }
159 
160 /*
161  * statext_is_kind_built
162  * Is this stat kind built in the given pg_statistic_ext_data tuple?
163  */
164 bool
166 {
168 
169  switch (type)
170  {
171  case STATS_EXT_NDISTINCT:
172  attnum = Anum_pg_statistic_ext_data_stxdndistinct;
173  break;
174 
175  case STATS_EXT_DEPENDENCIES:
176  attnum = Anum_pg_statistic_ext_data_stxddependencies;
177  break;
178 
179  case STATS_EXT_MCV:
180  attnum = Anum_pg_statistic_ext_data_stxdmcv;
181  break;
182 
183  default:
184  elog(ERROR, "unexpected statistics type requested: %d", type);
185  }
186 
187  return !heap_attisnull(htup, attnum, NULL);
188 }
189 
190 /*
191  * Return a list (of StatExtEntry) of statistics objects for the given relation.
192  */
193 static List *
195 {
196  SysScanDesc scan;
197  ScanKeyData skey;
198  HeapTuple htup;
199  List *result = NIL;
200 
201  /*
202  * Prepare to scan pg_statistic_ext for entries having stxrelid = this
203  * rel.
204  */
205  ScanKeyInit(&skey,
206  Anum_pg_statistic_ext_stxrelid,
207  BTEqualStrategyNumber, F_OIDEQ,
208  ObjectIdGetDatum(relid));
209 
210  scan = systable_beginscan(pg_statext, StatisticExtRelidIndexId, true,
211  NULL, 1, &skey);
212 
213  while (HeapTupleIsValid(htup = systable_getnext(scan)))
214  {
215  StatExtEntry *entry;
216  Datum datum;
217  bool isnull;
218  int i;
219  ArrayType *arr;
220  char *enabled;
221  Form_pg_statistic_ext staForm;
222 
223  entry = palloc0(sizeof(StatExtEntry));
224  staForm = (Form_pg_statistic_ext) GETSTRUCT(htup);
225  entry->statOid = staForm->oid;
226  entry->schema = get_namespace_name(staForm->stxnamespace);
227  entry->name = pstrdup(NameStr(staForm->stxname));
228  for (i = 0; i < staForm->stxkeys.dim1; i++)
229  {
230  entry->columns = bms_add_member(entry->columns,
231  staForm->stxkeys.values[i]);
232  }
233 
234  /* decode the stxkind char array into a list of chars */
235  datum = SysCacheGetAttr(STATEXTOID, htup,
236  Anum_pg_statistic_ext_stxkind, &isnull);
237  Assert(!isnull);
238  arr = DatumGetArrayTypeP(datum);
239  if (ARR_NDIM(arr) != 1 ||
240  ARR_HASNULL(arr) ||
241  ARR_ELEMTYPE(arr) != CHAROID)
242  elog(ERROR, "stxkind is not a 1-D char array");
243  enabled = (char *) ARR_DATA_PTR(arr);
244  for (i = 0; i < ARR_DIMS(arr)[0]; i++)
245  {
246  Assert((enabled[i] == STATS_EXT_NDISTINCT) ||
247  (enabled[i] == STATS_EXT_DEPENDENCIES) ||
248  (enabled[i] == STATS_EXT_MCV));
249  entry->types = lappend_int(entry->types, (int) enabled[i]);
250  }
251 
252  result = lappend(result, entry);
253  }
254 
255  systable_endscan(scan);
256 
257  return result;
258 }
259 
260 /*
261  * Using 'vacatts' of size 'nvacatts' as input data, return a newly built
262  * VacAttrStats array which includes only the items corresponding to
263  * attributes indicated by 'stxkeys'. If we don't have all of the per column
264  * stats available to compute the extended stats, then we return NULL to indicate
265  * to the caller that the stats should not be built.
266  */
267 static VacAttrStats **
269  int nvacatts, VacAttrStats **vacatts)
270 {
271  int i = 0;
272  int x = -1;
273  VacAttrStats **stats;
274 
275  stats = (VacAttrStats **)
276  palloc(bms_num_members(attrs) * sizeof(VacAttrStats *));
277 
278  /* lookup VacAttrStats info for the requested columns (same attnum) */
279  while ((x = bms_next_member(attrs, x)) >= 0)
280  {
281  int j;
282 
283  stats[i] = NULL;
284  for (j = 0; j < nvacatts; j++)
285  {
286  if (x == vacatts[j]->tupattnum)
287  {
288  stats[i] = vacatts[j];
289  break;
290  }
291  }
292 
293  if (!stats[i])
294  {
295  /*
296  * Looks like stats were not gathered for one of the columns
297  * required. We'll be unable to build the extended stats without
298  * this column.
299  */
300  pfree(stats);
301  return NULL;
302  }
303 
304  /*
305  * Sanity check that the column is not dropped - stats should have
306  * been removed in this case.
307  */
308  Assert(!stats[i]->attr->attisdropped);
309 
310  i++;
311  }
312 
313  return stats;
314 }
315 
316 /*
317  * statext_store
318  * Serializes the statistics and stores them into the pg_statistic_ext_data
319  * tuple.
320  */
321 static void
323  MVNDistinct *ndistinct, MVDependencies *dependencies,
324  MCVList *mcv, VacAttrStats **stats)
325 {
326  HeapTuple stup,
327  oldtup;
328  Datum values[Natts_pg_statistic_ext_data];
329  bool nulls[Natts_pg_statistic_ext_data];
330  bool replaces[Natts_pg_statistic_ext_data];
331  Relation pg_stextdata;
332 
333  memset(nulls, true, sizeof(nulls));
334  memset(replaces, false, sizeof(replaces));
335  memset(values, 0, sizeof(values));
336 
337  /*
338  * Construct a new pg_statistic_ext_data tuple, replacing the calculated
339  * stats.
340  */
341  if (ndistinct != NULL)
342  {
343  bytea *data = statext_ndistinct_serialize(ndistinct);
344 
345  nulls[Anum_pg_statistic_ext_data_stxdndistinct - 1] = (data == NULL);
346  values[Anum_pg_statistic_ext_data_stxdndistinct - 1] = PointerGetDatum(data);
347  }
348 
349  if (dependencies != NULL)
350  {
351  bytea *data = statext_dependencies_serialize(dependencies);
352 
353  nulls[Anum_pg_statistic_ext_data_stxddependencies - 1] = (data == NULL);
354  values[Anum_pg_statistic_ext_data_stxddependencies - 1] = PointerGetDatum(data);
355  }
356  if (mcv != NULL)
357  {
358  bytea *data = statext_mcv_serialize(mcv, stats);
359 
360  nulls[Anum_pg_statistic_ext_data_stxdmcv - 1] = (data == NULL);
361  values[Anum_pg_statistic_ext_data_stxdmcv - 1] = PointerGetDatum(data);
362  }
363 
364  /* always replace the value (either by bytea or NULL) */
365  replaces[Anum_pg_statistic_ext_data_stxdndistinct - 1] = true;
366  replaces[Anum_pg_statistic_ext_data_stxddependencies - 1] = true;
367  replaces[Anum_pg_statistic_ext_data_stxdmcv - 1] = true;
368 
369  /* there should already be a pg_statistic_ext_data tuple */
371  if (!HeapTupleIsValid(oldtup))
372  elog(ERROR, "cache lookup failed for statistics object %u", statOid);
373 
374  /* replace it */
375  pg_stextdata = table_open(StatisticExtDataRelationId, RowExclusiveLock);
376 
377  stup = heap_modify_tuple(oldtup,
378  RelationGetDescr(pg_stextdata),
379  values,
380  nulls,
381  replaces);
382  ReleaseSysCache(oldtup);
383  CatalogTupleUpdate(pg_stextdata, &stup->t_self, stup);
384 
385  heap_freetuple(stup);
386 
387  table_close(pg_stextdata, RowExclusiveLock);
388 }
389 
390 /* initialize multi-dimensional sort */
392 multi_sort_init(int ndims)
393 {
394  MultiSortSupport mss;
395 
396  Assert(ndims >= 2);
397 
399  + sizeof(SortSupportData) * ndims);
400 
401  mss->ndims = ndims;
402 
403  return mss;
404 }
405 
406 /*
407  * Prepare sort support info using the given sort operator and collation
408  * at the position 'sortdim'
409  */
410 void
412  Oid oper, Oid collation)
413 {
414  SortSupport ssup = &mss->ssup[sortdim];
415 
417  ssup->ssup_collation = collation;
418  ssup->ssup_nulls_first = false;
419 
421 }
422 
423 /* compare all the dimensions in the selected order */
424 int
425 multi_sort_compare(const void *a, const void *b, void *arg)
426 {
428  SortItem *ia = (SortItem *) a;
429  SortItem *ib = (SortItem *) b;
430  int i;
431 
432  for (i = 0; i < mss->ndims; i++)
433  {
434  int compare;
435 
436  compare = ApplySortComparator(ia->values[i], ia->isnull[i],
437  ib->values[i], ib->isnull[i],
438  &mss->ssup[i]);
439 
440  if (compare != 0)
441  return compare;
442  }
443 
444  /* equal by default */
445  return 0;
446 }
447 
448 /* compare selected dimension */
449 int
450 multi_sort_compare_dim(int dim, const SortItem *a, const SortItem *b,
451  MultiSortSupport mss)
452 {
453  return ApplySortComparator(a->values[dim], a->isnull[dim],
454  b->values[dim], b->isnull[dim],
455  &mss->ssup[dim]);
456 }
457 
458 int
459 multi_sort_compare_dims(int start, int end,
460  const SortItem *a, const SortItem *b,
461  MultiSortSupport mss)
462 {
463  int dim;
464 
465  for (dim = start; dim <= end; dim++)
466  {
467  int r = ApplySortComparator(a->values[dim], a->isnull[dim],
468  b->values[dim], b->isnull[dim],
469  &mss->ssup[dim]);
470 
471  if (r != 0)
472  return r;
473  }
474 
475  return 0;
476 }
477 
478 int
479 compare_scalars_simple(const void *a, const void *b, void *arg)
480 {
481  return compare_datums_simple(*(Datum *) a,
482  *(Datum *) b,
483  (SortSupport) arg);
484 }
485 
486 int
488 {
489  return ApplySortComparator(a, false, b, false, ssup);
490 }
491 
492 /* simple counterpart to qsort_arg */
493 void *
494 bsearch_arg(const void *key, const void *base, size_t nmemb, size_t size,
495  int (*compar) (const void *, const void *, void *),
496  void *arg)
497 {
498  size_t l,
499  u,
500  idx;
501  const void *p;
502  int comparison;
503 
504  l = 0;
505  u = nmemb;
506  while (l < u)
507  {
508  idx = (l + u) / 2;
509  p = (void *) (((const char *) base) + (idx * size));
510  comparison = (*compar) (key, p, arg);
511 
512  if (comparison < 0)
513  u = idx;
514  else if (comparison > 0)
515  l = idx + 1;
516  else
517  return (void *) p;
518  }
519 
520  return NULL;
521 }
522 
523 /*
524  * build_attnums_array
525  * Transforms a bitmap into an array of AttrNumber values.
526  *
527  * This is used for extended statistics only, so all the attribute must be
528  * user-defined. That means offsetting by FirstLowInvalidHeapAttributeNumber
529  * is not necessary here (and when querying the bitmap).
530  */
531 AttrNumber *
532 build_attnums_array(Bitmapset *attrs, int *numattrs)
533 {
534  int i,
535  j;
536  AttrNumber *attnums;
537  int num = bms_num_members(attrs);
538 
539  if (numattrs)
540  *numattrs = num;
541 
542  /* build attnums from the bitmapset */
543  attnums = (AttrNumber *) palloc(sizeof(AttrNumber) * num);
544  i = 0;
545  j = -1;
546  while ((j = bms_next_member(attrs, j)) >= 0)
547  {
548  /*
549  * Make sure the bitmap contains only user-defined attributes. As
550  * bitmaps can't contain negative values, this can be violated in two
551  * ways. Firstly, the bitmap might contain 0 as a member, and secondly
552  * the integer value might be larger than MaxAttrNumber.
553  */
555  Assert(j <= MaxAttrNumber);
556 
557  attnums[i++] = (AttrNumber) j;
558 
559  /* protect against overflows */
560  Assert(i <= num);
561  }
562 
563  return attnums;
564 }
565 
566 /*
567  * build_sorted_items
568  * build a sorted array of SortItem with values from rows
569  *
570  * Note: All the memory is allocated in a single chunk, so that the caller
571  * can simply pfree the return value to release all of it.
572  */
573 SortItem *
574 build_sorted_items(int numrows, int *nitems, HeapTuple *rows, TupleDesc tdesc,
575  MultiSortSupport mss, int numattrs, AttrNumber *attnums)
576 {
577  int i,
578  j,
579  len,
580  idx;
581  int nvalues = numrows * numattrs;
582 
583  SortItem *items;
584  Datum *values;
585  bool *isnull;
586  char *ptr;
587 
588  /* Compute the total amount of memory we need (both items and values). */
589  len = numrows * sizeof(SortItem) + nvalues * (sizeof(Datum) + sizeof(bool));
590 
591  /* Allocate the memory and split it into the pieces. */
592  ptr = palloc0(len);
593 
594  /* items to sort */
595  items = (SortItem *) ptr;
596  ptr += numrows * sizeof(SortItem);
597 
598  /* values and null flags */
599  values = (Datum *) ptr;
600  ptr += nvalues * sizeof(Datum);
601 
602  isnull = (bool *) ptr;
603  ptr += nvalues * sizeof(bool);
604 
605  /* make sure we consumed the whole buffer exactly */
606  Assert((ptr - (char *) items) == len);
607 
608  /* fix the pointers to Datum and bool arrays */
609  idx = 0;
610  for (i = 0; i < numrows; i++)
611  {
612  bool toowide = false;
613 
614  items[idx].values = &values[idx * numattrs];
615  items[idx].isnull = &isnull[idx * numattrs];
616 
617  /* load the values/null flags from sample rows */
618  for (j = 0; j < numattrs; j++)
619  {
620  Datum value;
621  bool isnull;
622 
623  value = heap_getattr(rows[i], attnums[j], tdesc, &isnull);
624 
625  /*
626  * If this is a varlena value, check if it's too wide and if yes
627  * then skip the whole item. Otherwise detoast the value.
628  *
629  * XXX It may happen that we've already detoasted some preceding
630  * values for the current item. We don't bother to cleanup those
631  * on the assumption that those are small (below WIDTH_THRESHOLD)
632  * and will be discarded at the end of analyze.
633  */
634  if ((!isnull) &&
635  (TupleDescAttr(tdesc, attnums[j] - 1)->attlen == -1))
636  {
638  {
639  toowide = true;
640  break;
641  }
642 
643  value = PointerGetDatum(PG_DETOAST_DATUM(value));
644  }
645 
646  items[idx].values[j] = value;
647  items[idx].isnull[j] = isnull;
648  }
649 
650  if (toowide)
651  continue;
652 
653  idx++;
654  }
655 
656  /* store the actual number of items (ignoring the too-wide ones) */
657  *nitems = idx;
658 
659  /* all items were too wide */
660  if (idx == 0)
661  {
662  /* everything is allocated as a single chunk */
663  pfree(items);
664  return NULL;
665  }
666 
667  /* do the sort, using the multi-sort */
668  qsort_arg((void *) items, idx, sizeof(SortItem),
669  multi_sort_compare, mss);
670 
671  return items;
672 }
673 
674 /*
675  * has_stats_of_kind
676  * Check whether the list contains statistic of a given kind
677  */
678 bool
679 has_stats_of_kind(List *stats, char requiredkind)
680 {
681  ListCell *l;
682 
683  foreach(l, stats)
684  {
686 
687  if (stat->kind == requiredkind)
688  return true;
689  }
690 
691  return false;
692 }
693 
694 /*
695  * choose_best_statistics
696  * Look for and return statistics with the specified 'requiredkind' which
697  * have keys that match at least two of the given attnums. Return NULL if
698  * there's no match.
699  *
700  * The current selection criteria is very simple - we choose the statistics
701  * object referencing the most of the requested attributes, breaking ties
702  * in favor of objects with fewer keys overall.
703  *
704  * XXX If multiple statistics objects tie on both criteria, then which object
705  * is chosen depends on the order that they appear in the stats list. Perhaps
706  * further tiebreakers are needed.
707  */
709 choose_best_statistics(List *stats, Bitmapset *attnums, char requiredkind)
710 {
711  ListCell *lc;
712  StatisticExtInfo *best_match = NULL;
713  int best_num_matched = 2; /* goal #1: maximize */
714  int best_match_keys = (STATS_MAX_DIMENSIONS + 1); /* goal #2: minimize */
715 
716  foreach(lc, stats)
717  {
718  StatisticExtInfo *info = (StatisticExtInfo *) lfirst(lc);
719  int num_matched;
720  int numkeys;
721  Bitmapset *matched;
722 
723  /* skip statistics that are not of the correct type */
724  if (info->kind != requiredkind)
725  continue;
726 
727  /* determine how many attributes of these stats can be matched to */
728  matched = bms_intersect(attnums, info->keys);
729  num_matched = bms_num_members(matched);
730  bms_free(matched);
731 
732  /*
733  * save the actual number of keys in the stats so that we can choose
734  * the narrowest stats with the most matching keys.
735  */
736  numkeys = bms_num_members(info->keys);
737 
738  /*
739  * Use this object when it increases the number of matched clauses or
740  * when it matches the same number of attributes but these stats have
741  * fewer keys than any previous match.
742  */
743  if (num_matched > best_num_matched ||
744  (num_matched == best_num_matched && numkeys < best_match_keys))
745  {
746  best_match = info;
747  best_num_matched = num_matched;
748  best_match_keys = numkeys;
749  }
750  }
751 
752  return best_match;
753 }
754 
755 /*
756  * statext_is_compatible_clause_internal
757  * Determines if the clause is compatible with MCV lists.
758  *
759  * Does the heavy lifting of actually inspecting the clauses for
760  * statext_is_compatible_clause. It needs to be split like this because
761  * of recursion. The attnums bitmap is an input/output parameter collecting
762  * attribute numbers from all compatible clauses (recursively).
763  */
764 static bool
766  Index relid, Bitmapset **attnums)
767 {
768  /* Look inside any binary-compatible relabeling (as in examine_variable) */
769  if (IsA(clause, RelabelType))
770  clause = (Node *) ((RelabelType *) clause)->arg;
771 
772  /* plain Var references (boolean Vars or recursive checks) */
773  if (IsA(clause, Var))
774  {
775  Var *var = (Var *) clause;
776 
777  /* Ensure var is from the correct relation */
778  if (var->varno != relid)
779  return false;
780 
781  /* we also better ensure the Var is from the current level */
782  if (var->varlevelsup > 0)
783  return false;
784 
785  /* Also skip system attributes (we don't allow stats on those). */
787  return false;
788 
789  *attnums = bms_add_member(*attnums, var->varattno);
790 
791  return true;
792  }
793 
794  /* (Var op Const) or (Const op Var) */
795  if (is_opclause(clause))
796  {
797  RangeTblEntry *rte = root->simple_rte_array[relid];
798  OpExpr *expr = (OpExpr *) clause;
799  Var *var;
800 
801  /* Only expressions with two arguments are considered compatible. */
802  if (list_length(expr->args) != 2)
803  return false;
804 
805  /* Check if the expression the right shape (one Var, one Const) */
806  if (!examine_opclause_expression(expr, &var, NULL, NULL))
807  return false;
808 
809  /*
810  * If it's not one of the supported operators ("=", "<", ">", etc.),
811  * just ignore the clause, as it's not compatible with MCV lists.
812  *
813  * This uses the function for estimating selectivity, not the operator
814  * directly (a bit awkward, but well ...).
815  */
816  switch (get_oprrest(expr->opno))
817  {
818  case F_EQSEL:
819  case F_NEQSEL:
820  case F_SCALARLTSEL:
821  case F_SCALARLESEL:
822  case F_SCALARGTSEL:
823  case F_SCALARGESEL:
824  /* supported, will continue with inspection of the Var */
825  break;
826 
827  default:
828  /* other estimators are considered unknown/unsupported */
829  return false;
830  }
831 
832  /*
833  * If there are any securityQuals on the RTE from security barrier
834  * views or RLS policies, then the user may not have access to all the
835  * table's data, and we must check that the operator is leak-proof.
836  *
837  * If the operator is leaky, then we must ignore this clause for the
838  * purposes of estimating with MCV lists, otherwise the operator might
839  * reveal values from the MCV list that the user doesn't have
840  * permission to see.
841  */
842  if (rte->securityQuals != NIL &&
844  return false;
845 
846  return statext_is_compatible_clause_internal(root, (Node *) var,
847  relid, attnums);
848  }
849 
850  /* AND/OR/NOT clause */
851  if (is_andclause(clause) ||
852  is_orclause(clause) ||
853  is_notclause(clause))
854  {
855  /*
856  * AND/OR/NOT-clauses are supported if all sub-clauses are supported
857  *
858  * Perhaps we could improve this by handling mixed cases, when some of
859  * the clauses are supported and some are not. Selectivity for the
860  * supported subclauses would be computed using extended statistics,
861  * and the remaining clauses would be estimated using the traditional
862  * algorithm (product of selectivities).
863  *
864  * It however seems overly complex, and in a way we already do that
865  * because if we reject the whole clause as unsupported here, it will
866  * be eventually passed to clauselist_selectivity() which does exactly
867  * this (split into supported/unsupported clauses etc).
868  */
869  BoolExpr *expr = (BoolExpr *) clause;
870  ListCell *lc;
871 
872  foreach(lc, expr->args)
873  {
874  /*
875  * Had we found incompatible clause in the arguments, treat the
876  * whole clause as incompatible.
877  */
879  (Node *) lfirst(lc),
880  relid, attnums))
881  return false;
882  }
883 
884  return true;
885  }
886 
887  /* Var IS NULL */
888  if (IsA(clause, NullTest))
889  {
890  NullTest *nt = (NullTest *) clause;
891 
892  /*
893  * Only simple (Var IS NULL) expressions supported for now. Maybe we
894  * could use examine_variable to fix this?
895  */
896  if (!IsA(nt->arg, Var))
897  return false;
898 
899  return statext_is_compatible_clause_internal(root, (Node *) (nt->arg),
900  relid, attnums);
901  }
902 
903  return false;
904 }
905 
906 /*
907  * statext_is_compatible_clause
908  * Determines if the clause is compatible with MCV lists.
909  *
910  * Currently, we only support three types of clauses:
911  *
912  * (a) OpExprs of the form (Var op Const), or (Const op Var), where the op
913  * is one of ("=", "<", ">", ">=", "<=")
914  *
915  * (b) (Var IS [NOT] NULL)
916  *
917  * (c) combinations using AND/OR/NOT
918  *
919  * In the future, the range of supported clauses may be expanded to more
920  * complex cases, for example (Var op Var).
921  */
922 static bool
924  Bitmapset **attnums)
925 {
926  RangeTblEntry *rte = root->simple_rte_array[relid];
927  RestrictInfo *rinfo = (RestrictInfo *) clause;
928  Oid userid;
929 
930  if (!IsA(rinfo, RestrictInfo))
931  return false;
932 
933  /* Pseudoconstants are not really interesting here. */
934  if (rinfo->pseudoconstant)
935  return false;
936 
937  /* clauses referencing multiple varnos are incompatible */
939  return false;
940 
941  /* Check the clause and determine what attributes it references. */
942  if (!statext_is_compatible_clause_internal(root, (Node *) rinfo->clause,
943  relid, attnums))
944  return false;
945 
946  /*
947  * Check that the user has permission to read all these attributes. Use
948  * checkAsUser if it's set, in case we're accessing the table via a view.
949  */
950  userid = rte->checkAsUser ? rte->checkAsUser : GetUserId();
951 
952  if (pg_class_aclcheck(rte->relid, userid, ACL_SELECT) != ACLCHECK_OK)
953  {
954  /* Don't have table privilege, must check individual columns */
955  if (bms_is_member(InvalidAttrNumber, *attnums))
956  {
957  /* Have a whole-row reference, must have access to all columns */
958  if (pg_attribute_aclcheck_all(rte->relid, userid, ACL_SELECT,
960  return false;
961  }
962  else
963  {
964  /* Check the columns referenced by the clause */
965  int attnum = -1;
966 
967  while ((attnum = bms_next_member(*attnums, attnum)) >= 0)
968  {
969  if (pg_attribute_aclcheck(rte->relid, attnum, userid,
971  return false;
972  }
973  }
974  }
975 
976  /* If we reach here, the clause is OK */
977  return true;
978 }
979 
980 /*
981  * statext_mcv_clauselist_selectivity
982  * Estimate clauses using the best multi-column statistics.
983  *
984  * Selects the best extended (multi-column) statistic on a table (measured by
985  * the number of attributes extracted from the clauses and covered by it), and
986  * computes the selectivity for the supplied clauses.
987  *
988  * One of the main challenges with using MCV lists is how to extrapolate the
989  * estimate to the data not covered by the MCV list. To do that, we compute
990  * not only the "MCV selectivity" (selectivities for MCV items matching the
991  * supplied clauses), but also a couple of derived selectivities:
992  *
993  * - simple selectivity: Computed without extended statistic, i.e. as if the
994  * columns/clauses were independent
995  *
996  * - base selectivity: Similar to simple selectivity, but is computed using
997  * the extended statistic by adding up the base frequencies (that we compute
998  * and store for each MCV item) of matching MCV items.
999  *
1000  * - total selectivity: Selectivity covered by the whole MCV list.
1001  *
1002  * - other selectivity: A selectivity estimate for data not covered by the MCV
1003  * list (i.e. satisfying the clauses, but not common enough to make it into
1004  * the MCV list)
1005  *
1006  * Note: While simple and base selectivities are defined in a quite similar
1007  * way, the values are computed differently and are not therefore equal. The
1008  * simple selectivity is computed as a product of per-clause estimates, while
1009  * the base selectivity is computed by adding up base frequencies of matching
1010  * items of the multi-column MCV list. So the values may differ for two main
1011  * reasons - (a) the MCV list may not cover 100% of the data and (b) some of
1012  * the MCV items did not match the estimated clauses.
1013  *
1014  * As both (a) and (b) reduce the base selectivity value, it generally holds
1015  * that (simple_selectivity >= base_selectivity). If the MCV list covers all
1016  * the data, the values may be equal.
1017  *
1018  * So, (simple_selectivity - base_selectivity) is an estimate for the part
1019  * not covered by the MCV list, and (mcv_selectivity - base_selectivity) may
1020  * be seen as a correction for the part covered by the MCV list. Those two
1021  * statements are actually equivalent.
1022  *
1023  * Note: Due to rounding errors and minor differences in how the estimates
1024  * are computed, the inequality may not always hold. Which is why we clamp
1025  * the selectivities to prevent strange estimate (negative etc.).
1026  *
1027  * 'estimatedclauses' is an input/output parameter. We set bits for the
1028  * 0-based 'clauses' indexes we estimate for and also skip clause items that
1029  * already have a bit set.
1030  *
1031  * XXX If we were to use multiple statistics, this is where it would happen.
1032  * We would simply repeat this on a loop on the "remaining" clauses, possibly
1033  * using the already estimated clauses as conditions (and combining the values
1034  * using conditional probability formula).
1035  */
1036 static Selectivity
1038  JoinType jointype, SpecialJoinInfo *sjinfo,
1039  RelOptInfo *rel, Bitmapset **estimatedclauses)
1040 {
1041  ListCell *l;
1042  Bitmapset *clauses_attnums = NULL;
1043  Bitmapset **list_attnums;
1044  int listidx;
1046  List *stat_clauses;
1047  Selectivity simple_sel,
1048  mcv_sel,
1049  mcv_basesel,
1050  mcv_totalsel,
1051  other_sel,
1052  sel;
1053 
1054  /* check if there's any stats that might be useful for us. */
1055  if (!has_stats_of_kind(rel->statlist, STATS_EXT_MCV))
1056  return 1.0;
1057 
1058  list_attnums = (Bitmapset **) palloc(sizeof(Bitmapset *) *
1059  list_length(clauses));
1060 
1061  /*
1062  * Pre-process the clauses list to extract the attnums seen in each item.
1063  * We need to determine if there's any clauses which will be useful for
1064  * selectivity estimations with extended stats. Along the way we'll record
1065  * all of the attnums for each clause in a list which we'll reference
1066  * later so we don't need to repeat the same work again. We'll also keep
1067  * track of all attnums seen.
1068  *
1069  * We also skip clauses that we already estimated using different types of
1070  * statistics (we treat them as incompatible).
1071  */
1072  listidx = 0;
1073  foreach(l, clauses)
1074  {
1075  Node *clause = (Node *) lfirst(l);
1076  Bitmapset *attnums = NULL;
1077 
1078  if (!bms_is_member(listidx, *estimatedclauses) &&
1079  statext_is_compatible_clause(root, clause, rel->relid, &attnums))
1080  {
1081  list_attnums[listidx] = attnums;
1082  clauses_attnums = bms_add_members(clauses_attnums, attnums);
1083  }
1084  else
1085  list_attnums[listidx] = NULL;
1086 
1087  listidx++;
1088  }
1089 
1090  /* We need at least two attributes for multivariate statistics. */
1091  if (bms_membership(clauses_attnums) != BMS_MULTIPLE)
1092  return 1.0;
1093 
1094  /* find the best suited statistics object for these attnums */
1095  stat = choose_best_statistics(rel->statlist, clauses_attnums, STATS_EXT_MCV);
1096 
1097  /* if no matching stats could be found then we've nothing to do */
1098  if (!stat)
1099  return 1.0;
1100 
1101  /* Ensure choose_best_statistics produced an expected stats type. */
1102  Assert(stat->kind == STATS_EXT_MCV);
1103 
1104  /* now filter the clauses to be estimated using the selected MCV */
1105  stat_clauses = NIL;
1106 
1107  listidx = 0;
1108  foreach(l, clauses)
1109  {
1110  /*
1111  * If the clause is compatible with the selected statistics, mark it
1112  * as estimated and add it to the list to estimate.
1113  */
1114  if (list_attnums[listidx] != NULL &&
1115  bms_is_subset(list_attnums[listidx], stat->keys))
1116  {
1117  stat_clauses = lappend(stat_clauses, (Node *) lfirst(l));
1118  *estimatedclauses = bms_add_member(*estimatedclauses, listidx);
1119  }
1120 
1121  listidx++;
1122  }
1123 
1124  /*
1125  * First compute "simple" selectivity, i.e. without the extended
1126  * statistics, and essentially assuming independence of the
1127  * columns/clauses. We'll then use the various selectivities computed from
1128  * MCV list to improve it.
1129  */
1130  simple_sel = clauselist_selectivity_simple(root, stat_clauses, varRelid,
1131  jointype, sjinfo, NULL);
1132 
1133  /*
1134  * Now compute the multi-column estimate from the MCV list, along with the
1135  * other selectivities (base & total selectivity).
1136  */
1137  mcv_sel = mcv_clauselist_selectivity(root, stat, stat_clauses, varRelid,
1138  jointype, sjinfo, rel,
1139  &mcv_basesel, &mcv_totalsel);
1140 
1141  /* Estimated selectivity of values not covered by MCV matches */
1142  other_sel = simple_sel - mcv_basesel;
1143  CLAMP_PROBABILITY(other_sel);
1144 
1145  /* The non-MCV selectivity can't exceed the 1 - mcv_totalsel. */
1146  if (other_sel > 1.0 - mcv_totalsel)
1147  other_sel = 1.0 - mcv_totalsel;
1148 
1149  /* Overall selectivity is the combination of MCV and non-MCV estimates. */
1150  sel = mcv_sel + other_sel;
1151  CLAMP_PROBABILITY(sel);
1152 
1153  return sel;
1154 }
1155 
1156 /*
1157  * statext_clauselist_selectivity
1158  * Estimate clauses using the best multi-column statistics.
1159  */
1161 statext_clauselist_selectivity(PlannerInfo *root, List *clauses, int varRelid,
1162  JoinType jointype, SpecialJoinInfo *sjinfo,
1163  RelOptInfo *rel, Bitmapset **estimatedclauses)
1164 {
1165  Selectivity sel;
1166 
1167  /* First, try estimating clauses using a multivariate MCV list. */
1168  sel = statext_mcv_clauselist_selectivity(root, clauses, varRelid, jointype,
1169  sjinfo, rel, estimatedclauses);
1170 
1171  /*
1172  * Then, apply functional dependencies on the remaining clauses by calling
1173  * dependencies_clauselist_selectivity. Pass 'estimatedclauses' so the
1174  * function can properly skip clauses already estimated above.
1175  *
1176  * The reasoning for applying dependencies last is that the more complex
1177  * stats can track more complex correlations between the attributes, and
1178  * so may be considered more reliable.
1179  *
1180  * For example, MCV list can give us an exact selectivity for values in
1181  * two columns, while functional dependencies can only provide information
1182  * about the overall strength of the dependency.
1183  */
1184  sel *= dependencies_clauselist_selectivity(root, clauses, varRelid,
1185  jointype, sjinfo, rel,
1186  estimatedclauses);
1187 
1188  return sel;
1189 }
1190 
1191 /*
1192  * examine_operator_expression
1193  * Split expression into Var and Const parts.
1194  *
1195  * Attempts to match the arguments to either (Var op Const) or (Const op Var),
1196  * possibly with a RelabelType on top. When the expression matches this form,
1197  * returns true, otherwise returns false.
1198  *
1199  * Optionally returns pointers to the extracted Var/Const nodes, when passed
1200  * non-null pointers (varp, cstp and varonleftp). The varonleftp flag specifies
1201  * on which side of the operator we found the Var node.
1202  */
1203 bool
1204 examine_opclause_expression(OpExpr *expr, Var **varp, Const **cstp, bool *varonleftp)
1205 {
1206  Var *var;
1207  Const *cst;
1208  bool varonleft;
1209  Node *leftop,
1210  *rightop;
1211 
1212  /* enforced by statext_is_compatible_clause_internal */
1213  Assert(list_length(expr->args) == 2);
1214 
1215  leftop = linitial(expr->args);
1216  rightop = lsecond(expr->args);
1217 
1218  /* strip RelabelType from either side of the expression */
1219  if (IsA(leftop, RelabelType))
1220  leftop = (Node *) ((RelabelType *) leftop)->arg;
1221 
1222  if (IsA(rightop, RelabelType))
1223  rightop = (Node *) ((RelabelType *) rightop)->arg;
1224 
1225  if (IsA(leftop, Var) && IsA(rightop, Const))
1226  {
1227  var = (Var *) leftop;
1228  cst = (Const *) rightop;
1229  varonleft = true;
1230  }
1231  else if (IsA(leftop, Const) && IsA(rightop, Var))
1232  {
1233  var = (Var *) rightop;
1234  cst = (Const *) leftop;
1235  varonleft = false;
1236  }
1237  else
1238  return false;
1239 
1240  /* return pointers to the extracted parts if requested */
1241  if (varp)
1242  *varp = var;
1243 
1244  if (cstp)
1245  *cstp = cst;
1246 
1247  if (varonleftp)
1248  *varonleftp = varonleft;
1249 
1250  return true;
1251 }
bool ssup_nulls_first
Definition: sortsupport.h:75
#define NIL
Definition: pg_list.h:65
Selectivity dependencies_clauselist_selectivity(PlannerInfo *root, List *clauses, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo, RelOptInfo *rel, Bitmapset **estimatedclauses)
Definition: dependencies.c:941
bool get_func_leakproof(Oid funcid)
Definition: lsyscache.c:1639
#define IsA(nodeptr, _type_)
Definition: nodes.h:575
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:211
#define AllocSetContextCreate
Definition: memutils.h:169
List * statlist
Definition: pathnodes.h:679
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
Index varlevelsup
Definition: primnodes.h:177
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:525
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
void * bsearch_arg(const void *key, const void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *, void *), void *arg)
AclResult pg_attribute_aclcheck(Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mode)
Definition: aclchk.c:4517
#define RelationGetDescr(relation)
Definition: rel.h:442
Oid GetUserId(void)
Definition: miscinit.c:380
static bool is_orclause(const void *clause)
Definition: nodeFuncs.h:102
#define MaxAttrNumber
Definition: attnum.h:24
#define PointerGetDatum(X)
Definition: postgres.h:556
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
List * securityQuals
Definition: parsenodes.h:1102
char * pstrdup(const char *in)
Definition: mcxt.c:1161
Relids clause_relids
Definition: pathnodes.h:1958
int bms_next_member(const Bitmapset *a, int prevbit)
Definition: bitmapset.c:1043
bool pseudoconstant
Definition: pathnodes.h:1951
void PrepareSortSupportFromOrderingOp(Oid orderingOp, SortSupport ssup)
Definition: sortsupport.c:134
static struct @144 value
static bool is_andclause(const void *clause)
Definition: nodeFuncs.h:93
SortItem * build_sorted_items(int numrows, int *nitems, HeapTuple *rows, TupleDesc tdesc, MultiSortSupport mss, int numattrs, AttrNumber *attnums)
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define AttrNumberIsForUserDefinedAttr(attributeNumber)
Definition: attnum.h:41
Definition: nodes.h:524
int multi_sort_compare_dims(int start, int end, const SortItem *a, const SortItem *b, MultiSortSupport mss)
int errcode(int sqlerrcode)
Definition: elog.c:570
AttrNumber varattno
Definition: primnodes.h:172
MCVList * statext_mcv_build(int numrows, HeapTuple *rows, Bitmapset *attrs, VacAttrStats **stats, double totalrows)
Definition: mcv.c:183
bool heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc)
Definition: heaptuple.c:359
Datum idx(PG_FUNCTION_ARGS)
Definition: _int_op.c:264
bool statext_is_kind_built(HeapTuple htup, char type)
double Selectivity
Definition: nodes.h:657
static List * fetch_statentries_for_relation(Relation pg_statext, Oid relid)
Form_pg_class rd_rel
Definition: rel.h:83
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
unsigned int Oid
Definition: postgres_ext.h:31
#define StatisticExtRelidIndexId
Definition: indexing.h:238
Definition: primnodes.h:167
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:352
Selectivity clauselist_selectivity_simple(PlannerInfo *root, List *clauses, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo, Bitmapset *estimatedclauses)
Definition: clausesel.c:151
#define lsecond(l)
Definition: pg_list.h:200
JoinType
Definition: nodes.h:691
Bitmapset * columns
#define CLAMP_PROBABILITY(p)
Definition: selfuncs.h:56
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:444
void pfree(void *pointer)
Definition: mcxt.c:1031
Size toast_raw_datum_size(Datum value)
Definition: tuptoaster.c:357
#define linitial(l)
Definition: pg_list.h:195
static int compare(const void *arg1, const void *arg2)
Definition: geqo_pool.c:145
SortSupportData ssup[FLEXIBLE_ARRAY_MEMBER]
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
void multi_sort_add_dimension(MultiSortSupport mss, int sortdim, Oid oper, Oid collation)
#define lfirst_int(lc)
Definition: pg_list.h:191
#define ARR_DIMS(a)
Definition: array.h:282
MemoryContext ssup_cxt
Definition: sortsupport.h:66
static Selectivity statext_mcv_clauselist_selectivity(PlannerInfo *root, List *clauses, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo, RelOptInfo *rel, Bitmapset **estimatedclauses)
Expr * arg
Definition: primnodes.h:1205
ItemPointerData t_self
Definition: htup.h:65
void BuildRelationExtStatistics(Relation onerel, double totalrows, int numrows, HeapTuple *rows, int natts, VacAttrStats **vacattrstats)
bytea * statext_mcv_serialize(MCVList *mcvlist, VacAttrStats **stats)
Definition: mcv.c:621
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:315
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:191
int bms_num_members(const Bitmapset *a)
Definition: bitmapset.c:646
#define ARR_DATA_PTR(a)
Definition: array.h:310
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3094
int multi_sort_compare_dim(int dim, const SortItem *a, const SortItem *b, MultiSortSupport mss)
AttrNumber * build_attnums_array(Bitmapset *attrs, int *numattrs)
#define RowExclusiveLock
Definition: lockdefs.h:38
#define RelationGetRelationName(relation)
Definition: rel.h:450
int compare_scalars_simple(const void *a, const void *b, void *arg)
#define ARR_HASNULL(a)
Definition: array.h:279
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
Selectivity statext_clauselist_selectivity(PlannerInfo *root, List *clauses, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo, RelOptInfo *rel, Bitmapset **estimatedclauses)
bool IsAutoVacuumWorkerProcess(void)
Definition: autovacuum.c:3278
#define ereport(elevel, rest)
Definition: elog.h:141
MultiSortSupport multi_sort_init(int ndims)
List * lappend_int(List *list, int datum)
Definition: list.c:339
Index relid
Definition: pathnodes.h:669
List * lappend(List *list, void *datum)
Definition: list.c:321
RangeTblEntry ** simple_rte_array
Definition: pathnodes.h:209
Expr * clause
Definition: pathnodes.h:1943
void qsort_arg(void *base, size_t nel, size_t elsize, qsort_arg_comparator cmp, void *arg)
Definition: qsort_arg.c:113
int16 attlen
Definition: pg_attribute.h:64
#define WARNING
Definition: elog.h:40
Index varno
Definition: primnodes.h:170
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:762
#define stat(a, b)
Definition: win32_port.h:264
struct SortSupportData SortSupportData
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1124
static bool is_notclause(const void *clause)
Definition: nodeFuncs.h:111
int compare_datums_simple(Datum a, Datum b, SortSupport ssup)
RegProcedure get_oprrest(Oid opno)
Definition: lsyscache.c:1359
MVDependencies * statext_dependencies_build(int numrows, HeapTuple *rows, Bitmapset *attrs, VacAttrStats **stats)
Definition: dependencies.c:357
BMS_Membership bms_membership(const Bitmapset *a)
Definition: bitmapset.c:672
void * palloc0(Size size)
Definition: mcxt.c:955
uintptr_t Datum
Definition: postgres.h:367
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1172
#define ACL_SELECT
Definition: parsenodes.h:75
struct SortItem SortItem
Bitmapset * bms_intersect(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:259
StatisticExtInfo * choose_best_statistics(List *stats, Bitmapset *attnums, char requiredkind)
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1385
bytea * statext_ndistinct_serialize(MVNDistinct *ndistinct)
Definition: mvdistinct.c:172
#define WIDTH_THRESHOLD
struct StatExtEntry StatExtEntry
unsigned int Index
Definition: c.h:475
RegProcedure get_opcode(Oid opno)
Definition: lsyscache.c:1092
int16 attnum
Definition: pg_attribute.h:79
MVNDistinct * statext_ndistinct_build(double totalrows, int numrows, HeapTuple *rows, Bitmapset *attrs, VacAttrStats **stats)
Definition: mvdistinct.c:87
void bms_free(Bitmapset *a)
Definition: bitmapset.c:208
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:732
#define lfirst(lc)
Definition: pg_list.h:190
int multi_sort_compare(const void *a, const void *b, void *arg)
AclResult pg_attribute_aclcheck_all(Oid table_oid, Oid roleid, AclMode mode, AclMaskHow how)
Definition: aclchk.c:4546
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:224
static int list_length(const List *l)
Definition: pg_list.h:169
static bool statext_is_compatible_clause(PlannerInfo *root, Node *clause, Index relid, Bitmapset **attnums)
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:736
#define ARR_NDIM(a)
Definition: array.h:278
List * args
Definition: primnodes.h:569
#define InvalidAttrNumber
Definition: attnum.h:23
AclResult pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4631
static void statext_store(Oid relid, MVNDistinct *ndistinct, MVDependencies *dependencies, MCVList *mcv, VacAttrStats **stats)
static Datum values[MAXATTR]
Definition: bootstrap.c:167
static bool statext_is_compatible_clause_internal(PlannerInfo *root, Node *clause, Index relid, Bitmapset **attnums)
Bitmapset * keys
Definition: pathnodes.h:885
#define STATS_MAX_DIMENSIONS
Definition: statistics.h:19
void * palloc(Size size)
Definition: mcxt.c:924
int errmsg(const char *fmt,...)
Definition: elog.c:784
bytea * statext_dependencies_serialize(MVDependencies *dependencies)
Definition: dependencies.c:446
#define elog(elevel,...)
Definition: elog.h:226
int i
#define NameStr(name)
Definition: c.h:609
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
Selectivity mcv_clauselist_selectivity(PlannerInfo *root, StatisticExtInfo *stat, List *clauses, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo, RelOptInfo *rel, Selectivity *basesel, Selectivity *totalsel)
Definition: mcv.c:1797
void * arg
#define PG_DETOAST_DATUM(datum)
Definition: fmgr.h:235
Definition: c.h:549
MultiSortSupportData * MultiSortSupport
Oid opno
Definition: primnodes.h:502
static bool is_opclause(const void *clause)
Definition: nodeFuncs.h:62
bool examine_opclause_expression(OpExpr *expr, Var **varp, Const **cstp, bool *varonleftp)
List * args
Definition: primnodes.h:508
Operator oper(ParseState *pstate, List *opname, Oid ltypeId, Oid rtypeId, bool noError, int location)
Definition: parse_oper.c:377
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
static int ApplySortComparator(Datum datum1, bool isNull1, Datum datum2, bool isNull2, SortSupport ssup)
Definition: sortsupport.h:200
Definition: pg_list.h:50
int errtable(Relation rel)
Definition: relcache.c:5168
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:427
bool has_stats_of_kind(List *stats, char requiredkind)
#define ARR_ELEMTYPE(a)
Definition: array.h:280
static VacAttrStats ** lookup_var_attr_stats(Relation rel, Bitmapset *attrs, int nvacatts, VacAttrStats **vacatts)
int16 AttrNumber
Definition: attnum.h:21
#define RelationGetRelid(relation)
Definition: rel.h:416
#define BTEqualStrategyNumber
Definition: stratnum.h:31
#define offsetof(type, field)
Definition: c.h:655
Bitmapset * bms_add_members(Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:793
FormData_pg_statistic_ext * Form_pg_statistic_ext
unsigned char bool
Definition: c.h:308
#define DatumGetArrayTypeP(X)
Definition: array.h:249