PostgreSQL Source Code  git master
statistics.h File Reference
#include "commands/vacuum.h"
#include "nodes/pathnodes.h"
Include dependency graph for statistics.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  MVNDistinctItem
 
struct  MVNDistinct
 
struct  MVDependency
 
struct  MVDependencies
 
struct  MCVItem
 
struct  MCVList
 

Macros

#define STATS_MAX_DIMENSIONS   8 /* max number of attributes */
 
#define STATS_NDISTINCT_MAGIC   0xA352BFA4 /* struct identifier */
 
#define STATS_NDISTINCT_TYPE_BASIC   1 /* struct version */
 
#define STATS_DEPS_MAGIC   0xB4549A2C /* marks serialized bytea */
 
#define STATS_DEPS_TYPE_BASIC   1 /* basic dependencies type */
 
#define STATS_MCV_MAGIC   0xE1A651C2 /* marks serialized bytea */
 
#define STATS_MCV_TYPE_BASIC   1 /* basic MCV list type */
 
#define STATS_MCVLIST_MAX_ITEMS   10000
 

Typedefs

typedef struct MVNDistinctItem MVNDistinctItem
 
typedef struct MVNDistinct MVNDistinct
 
typedef struct MVDependency MVDependency
 
typedef struct MVDependencies MVDependencies
 
typedef struct MCVItem MCVItem
 
typedef struct MCVList MCVList
 

Functions

MVNDistinctstatext_ndistinct_load (Oid mvoid, bool inh)
 
MVDependenciesstatext_dependencies_load (Oid mvoid, bool inh)
 
MCVListstatext_mcv_load (Oid mvoid, bool inh)
 
void BuildRelationExtStatistics (Relation onerel, bool inh, double totalrows, int numrows, HeapTuple *rows, int natts, VacAttrStats **vacattrstats)
 
int ComputeExtStatisticsRows (Relation onerel, int natts, VacAttrStats **stats)
 
bool statext_is_kind_built (HeapTuple htup, char kind)
 
Selectivity dependencies_clauselist_selectivity (PlannerInfo *root, List *clauses, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo, RelOptInfo *rel, Bitmapset **estimatedclauses)
 
Selectivity statext_clauselist_selectivity (PlannerInfo *root, List *clauses, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo, RelOptInfo *rel, Bitmapset **estimatedclauses, bool is_or)
 
bool has_stats_of_kind (List *stats, char requiredkind)
 
StatisticExtInfochoose_best_statistics (List *stats, char requiredkind, bool inh, Bitmapset **clause_attnums, List **clause_exprs, int nclauses)
 
HeapTuple statext_expressions_load (Oid stxoid, bool inh, int idx)
 

Macro Definition Documentation

◆ STATS_DEPS_MAGIC

#define STATS_DEPS_MAGIC   0xB4549A2C /* marks serialized bytea */

Definition at line 43 of file statistics.h.

◆ STATS_DEPS_TYPE_BASIC

#define STATS_DEPS_TYPE_BASIC   1 /* basic dependencies type */

Definition at line 44 of file statistics.h.

◆ STATS_MAX_DIMENSIONS

#define STATS_MAX_DIMENSIONS   8 /* max number of attributes */

Definition at line 19 of file statistics.h.

◆ STATS_MCV_MAGIC

#define STATS_MCV_MAGIC   0xE1A651C2 /* marks serialized bytea */

Definition at line 66 of file statistics.h.

◆ STATS_MCV_TYPE_BASIC

#define STATS_MCV_TYPE_BASIC   1 /* basic MCV list type */

Definition at line 67 of file statistics.h.

◆ STATS_MCVLIST_MAX_ITEMS

#define STATS_MCVLIST_MAX_ITEMS   10000

Definition at line 70 of file statistics.h.

◆ STATS_NDISTINCT_MAGIC

#define STATS_NDISTINCT_MAGIC   0xA352BFA4 /* struct identifier */

Definition at line 22 of file statistics.h.

◆ STATS_NDISTINCT_TYPE_BASIC

#define STATS_NDISTINCT_TYPE_BASIC   1 /* struct version */

Definition at line 23 of file statistics.h.

Typedef Documentation

◆ MCVItem

typedef struct MCVItem MCVItem

◆ MCVList

typedef struct MCVList MCVList

◆ MVDependencies

◆ MVDependency

typedef struct MVDependency MVDependency

◆ MVNDistinct

typedef struct MVNDistinct MVNDistinct

◆ MVNDistinctItem

Function Documentation

◆ BuildRelationExtStatistics()

void BuildRelationExtStatistics ( Relation  onerel,
bool  inh,
double  totalrows,
int  numrows,
HeapTuple rows,
int  natts,
VacAttrStats **  vacattrstats 
)

Definition at line 115 of file extended_stats.c.

118 {
119  Relation pg_stext;
120  ListCell *lc;
121  List *statslist;
122  MemoryContext cxt;
123  MemoryContext oldcxt;
124  int64 ext_cnt;
125 
126  /* Do nothing if there are no columns to analyze. */
127  if (!natts)
128  return;
129 
130  /* the list of stats has to be allocated outside the memory context */
131  pg_stext = table_open(StatisticExtRelationId, RowExclusiveLock);
132  statslist = fetch_statentries_for_relation(pg_stext, RelationGetRelid(onerel));
133 
134  /* memory context for building each statistics object */
136  "BuildRelationExtStatistics",
138  oldcxt = MemoryContextSwitchTo(cxt);
139 
140  /* report this phase */
141  if (statslist != NIL)
142  {
143  const int index[] = {
146  };
147  const int64 val[] = {
149  list_length(statslist)
150  };
151 
153  }
154 
155  ext_cnt = 0;
156  foreach(lc, statslist)
157  {
159  MVNDistinct *ndistinct = NULL;
160  MVDependencies *dependencies = NULL;
161  MCVList *mcv = NULL;
162  Datum exprstats = (Datum) 0;
163  VacAttrStats **stats;
164  ListCell *lc2;
165  int stattarget;
167 
168  /*
169  * Check if we can build these stats based on the column analyzed. If
170  * not, report this fact (except in autovacuum) and move on.
171  */
172  stats = lookup_var_attr_stats(onerel, stat->columns, stat->exprs,
173  natts, vacattrstats);
174  if (!stats)
175  {
178  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
179  errmsg("statistics object \"%s.%s\" could not be computed for relation \"%s.%s\"",
180  stat->schema, stat->name,
181  get_namespace_name(onerel->rd_rel->relnamespace),
182  RelationGetRelationName(onerel)),
183  errtable(onerel)));
184  continue;
185  }
186 
187  /* compute statistics target for this statistics object */
188  stattarget = statext_compute_stattarget(stat->stattarget,
189  bms_num_members(stat->columns),
190  stats);
191 
192  /*
193  * Don't rebuild statistics objects with statistics target set to 0
194  * (we just leave the existing values around, just like we do for
195  * regular per-column statistics).
196  */
197  if (stattarget == 0)
198  continue;
199 
200  /* evaluate expressions (if the statistics object has any) */
201  data = make_build_data(onerel, stat, numrows, rows, stats, stattarget);
202 
203  /* compute statistic of each requested type */
204  foreach(lc2, stat->types)
205  {
206  char t = (char) lfirst_int(lc2);
207 
208  if (t == STATS_EXT_NDISTINCT)
209  ndistinct = statext_ndistinct_build(totalrows, data);
210  else if (t == STATS_EXT_DEPENDENCIES)
211  dependencies = statext_dependencies_build(data);
212  else if (t == STATS_EXT_MCV)
213  mcv = statext_mcv_build(data, totalrows, stattarget);
214  else if (t == STATS_EXT_EXPRESSIONS)
215  {
216  AnlExprData *exprdata;
217  int nexprs;
218 
219  /* should not happen, thanks to checks when defining stats */
220  if (!stat->exprs)
221  elog(ERROR, "requested expression stats, but there are no expressions");
222 
223  exprdata = build_expr_data(stat->exprs, stattarget);
224  nexprs = list_length(stat->exprs);
225 
226  compute_expr_stats(onerel, totalrows,
227  exprdata, nexprs,
228  rows, numrows);
229 
230  exprstats = serialize_expr_stats(exprdata, nexprs);
231  }
232  }
233 
234  /* store the statistics in the catalog */
235  statext_store(stat->statOid, inh,
236  ndistinct, dependencies, mcv, exprstats, stats);
237 
238  /* for reporting progress */
240  ++ext_cnt);
241 
242  /* free the data used for building this statistics object */
243  MemoryContextReset(cxt);
244  }
245 
246  MemoryContextSwitchTo(oldcxt);
247  MemoryContextDelete(cxt);
248 
249  list_free(statslist);
250 
251  table_close(pg_stext, RowExclusiveLock);
252 }
bool IsAutoVacuumWorkerProcess(void)
Definition: autovacuum.c:3309
void pgstat_progress_update_param(int index, int64 val)
void pgstat_progress_update_multi_param(int nparam, const int *index, const int64 *val)
int bms_num_members(const Bitmapset *a)
Definition: bitmapset.c:648
MVDependencies * statext_dependencies_build(StatsBuildData *data)
Definition: dependencies.c:350
int errcode(int sqlerrcode)
Definition: elog.c:693
int errmsg(const char *fmt,...)
Definition: elog.c:904
#define WARNING
Definition: elog.h:30
#define ERROR
Definition: elog.h:33
#define elog(elevel,...)
Definition: elog.h:218
#define ereport(elevel,...)
Definition: elog.h:143
static StatsBuildData * make_build_data(Relation onerel, StatExtEntry *stat, int numrows, HeapTuple *rows, VacAttrStats **stats, int stattarget)
static int statext_compute_stattarget(int stattarget, int natts, VacAttrStats **stats)
static AnlExprData * build_expr_data(List *exprs, int stattarget)
static VacAttrStats ** lookup_var_attr_stats(Relation rel, Bitmapset *attrs, List *exprs, int nvacatts, VacAttrStats **vacatts)
static List * fetch_statentries_for_relation(Relation pg_statext, Oid relid)
static void statext_store(Oid statOid, bool inh, MVNDistinct *ndistinct, MVDependencies *dependencies, MCVList *mcv, Datum exprs, VacAttrStats **stats)
static void compute_expr_stats(Relation onerel, double totalrows, AnlExprData *exprdata, int nexprs, HeapTuple *rows, int numrows)
static Datum serialize_expr_stats(AnlExprData *exprdata, int nexprs)
long val
Definition: informix.c:664
void list_free(List *list)
Definition: list.c:1505
#define RowExclusiveLock
Definition: lockdefs.h:38
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3326
MCVList * statext_mcv_build(StatsBuildData *data, double totalrows, int stattarget)
Definition: mcv.c:184
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:143
MemoryContext CurrentMemoryContext
Definition: mcxt.c:42
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:218
#define AllocSetContextCreate
Definition: memutils.h:173
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:197
MVNDistinct * statext_ndistinct_build(double totalrows, StatsBuildData *data)
Definition: mvdistinct.c:89
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
const void * data
#define lfirst(lc)
Definition: pg_list.h:169
static int list_length(const List *l)
Definition: pg_list.h:149
#define NIL
Definition: pg_list.h:65
#define lfirst_int(lc)
Definition: pg_list.h:170
uintptr_t Datum
Definition: postgres.h:411
#define PROGRESS_ANALYZE_EXT_STATS_COMPUTED
Definition: progress.h:42
#define PROGRESS_ANALYZE_PHASE
Definition: progress.h:38
#define PROGRESS_ANALYZE_PHASE_COMPUTE_EXT_STATS
Definition: progress.h:51
#define PROGRESS_ANALYZE_EXT_STATS_TOTAL
Definition: progress.h:41
#define RelationGetRelid(relation)
Definition: rel.h:489
#define RelationGetRelationName(relation)
Definition: rel.h:523
int errtable(Relation rel)
Definition: relcache.c:5819
Definition: pg_list.h:51
Form_pg_class rd_rel
Definition: rel.h:109
Definition: type.h:90
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, bms_num_members(), build_expr_data(), compute_expr_stats(), CurrentMemoryContext, data, elog, ereport, errcode(), errmsg(), ERROR, errtable(), fetch_statentries_for_relation(), get_namespace_name(), IsAutoVacuumWorkerProcess(), lfirst, lfirst_int, list_free(), list_length(), lookup_var_attr_stats(), make_build_data(), MemoryContextDelete(), MemoryContextReset(), MemoryContextSwitchTo(), NIL, pgstat_progress_update_multi_param(), pgstat_progress_update_param(), PROGRESS_ANALYZE_EXT_STATS_COMPUTED, PROGRESS_ANALYZE_EXT_STATS_TOTAL, PROGRESS_ANALYZE_PHASE, PROGRESS_ANALYZE_PHASE_COMPUTE_EXT_STATS, RelationData::rd_rel, RelationGetRelationName, RelationGetRelid, RowExclusiveLock, serialize_expr_stats(), statext_compute_stattarget(), statext_dependencies_build(), statext_mcv_build(), statext_ndistinct_build(), statext_store(), table_close(), table_open(), val, and WARNING.

Referenced by do_analyze_rel().

◆ choose_best_statistics()

StatisticExtInfo* choose_best_statistics ( List stats,
char  requiredkind,
bool  inh,
Bitmapset **  clause_attnums,
List **  clause_exprs,
int  nclauses 
)

Definition at line 1234 of file extended_stats.c.

1237 {
1238  ListCell *lc;
1239  StatisticExtInfo *best_match = NULL;
1240  int best_num_matched = 2; /* goal #1: maximize */
1241  int best_match_keys = (STATS_MAX_DIMENSIONS + 1); /* goal #2: minimize */
1242 
1243  foreach(lc, stats)
1244  {
1245  int i;
1246  StatisticExtInfo *info = (StatisticExtInfo *) lfirst(lc);
1247  Bitmapset *matched_attnums = NULL;
1248  Bitmapset *matched_exprs = NULL;
1249  int num_matched;
1250  int numkeys;
1251 
1252  /* skip statistics that are not of the correct type */
1253  if (info->kind != requiredkind)
1254  continue;
1255 
1256  /* skip statistics with mismatching inheritance flag */
1257  if (info->inherit != inh)
1258  continue;
1259 
1260  /*
1261  * Collect attributes and expressions in remaining (unestimated)
1262  * clauses fully covered by this statistic object.
1263  *
1264  * We know already estimated clauses have both clause_attnums and
1265  * clause_exprs set to NULL. We leave the pointers NULL if already
1266  * estimated, or we reset them to NULL after estimating the clause.
1267  */
1268  for (i = 0; i < nclauses; i++)
1269  {
1270  Bitmapset *expr_idxs = NULL;
1271 
1272  /* ignore incompatible/estimated clauses */
1273  if (!clause_attnums[i] && !clause_exprs[i])
1274  continue;
1275 
1276  /* ignore clauses that are not covered by this object */
1277  if (!bms_is_subset(clause_attnums[i], info->keys) ||
1278  !stat_covers_expressions(info, clause_exprs[i], &expr_idxs))
1279  continue;
1280 
1281  /* record attnums and indexes of expressions covered */
1282  matched_attnums = bms_add_members(matched_attnums, clause_attnums[i]);
1283  matched_exprs = bms_add_members(matched_exprs, expr_idxs);
1284  }
1285 
1286  num_matched = bms_num_members(matched_attnums) + bms_num_members(matched_exprs);
1287 
1288  bms_free(matched_attnums);
1289  bms_free(matched_exprs);
1290 
1291  /*
1292  * save the actual number of keys in the stats so that we can choose
1293  * the narrowest stats with the most matching keys.
1294  */
1295  numkeys = bms_num_members(info->keys) + list_length(info->exprs);
1296 
1297  /*
1298  * Use this object when it increases the number of matched attributes
1299  * and expressions or when it matches the same number of attributes
1300  * and expressions but these stats have fewer keys than any previous
1301  * match.
1302  */
1303  if (num_matched > best_num_matched ||
1304  (num_matched == best_num_matched && numkeys < best_match_keys))
1305  {
1306  best_match = info;
1307  best_num_matched = num_matched;
1308  best_match_keys = numkeys;
1309  }
1310  }
1311 
1312  return best_match;
1313 }
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:315
void bms_free(Bitmapset *a)
Definition: bitmapset.c:208
Bitmapset * bms_add_members(Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:795
static bool stat_covers_expressions(StatisticExtInfo *stat, List *exprs, Bitmapset **expr_idxs)
int i
Definition: isn.c:73
#define STATS_MAX_DIMENSIONS
Definition: statistics.h:19
Bitmapset * keys
Definition: pathnodes.h:941

References bms_add_members(), bms_free(), bms_is_subset(), bms_num_members(), StatisticExtInfo::exprs, i, StatisticExtInfo::inherit, StatisticExtInfo::keys, StatisticExtInfo::kind, lfirst, list_length(), stat_covers_expressions(), and STATS_MAX_DIMENSIONS.

Referenced by statext_mcv_clauselist_selectivity().

◆ ComputeExtStatisticsRows()

int ComputeExtStatisticsRows ( Relation  onerel,
int  natts,
VacAttrStats **  stats 
)

Definition at line 268 of file extended_stats.c.

270 {
271  Relation pg_stext;
272  ListCell *lc;
273  List *lstats;
274  MemoryContext cxt;
275  MemoryContext oldcxt;
276  int result = 0;
277 
278  /* If there are no columns to analyze, just return 0. */
279  if (!natts)
280  return 0;
281 
283  "ComputeExtStatisticsRows",
285  oldcxt = MemoryContextSwitchTo(cxt);
286 
287  pg_stext = table_open(StatisticExtRelationId, RowExclusiveLock);
288  lstats = fetch_statentries_for_relation(pg_stext, RelationGetRelid(onerel));
289 
290  foreach(lc, lstats)
291  {
293  int stattarget;
294  VacAttrStats **stats;
295  int nattrs = bms_num_members(stat->columns);
296 
297  /*
298  * Check if we can build this statistics object based on the columns
299  * analyzed. If not, ignore it (don't report anything, we'll do that
300  * during the actual build BuildRelationExtStatistics).
301  */
302  stats = lookup_var_attr_stats(onerel, stat->columns, stat->exprs,
303  natts, vacattrstats);
304 
305  if (!stats)
306  continue;
307 
308  /*
309  * Compute statistics target, based on what's set for the statistic
310  * object itself, and for its attributes.
311  */
312  stattarget = statext_compute_stattarget(stat->stattarget,
313  nattrs, stats);
314 
315  /* Use the largest value for all statistics objects. */
316  if (stattarget > result)
317  result = stattarget;
318  }
319 
320  table_close(pg_stext, RowExclusiveLock);
321 
322  MemoryContextSwitchTo(oldcxt);
323  MemoryContextDelete(cxt);
324 
325  /* compute sample size based on the statistics target */
326  return (300 * result);
327 }

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, bms_num_members(), CurrentMemoryContext, fetch_statentries_for_relation(), lfirst, lookup_var_attr_stats(), MemoryContextDelete(), MemoryContextSwitchTo(), RelationGetRelid, RowExclusiveLock, statext_compute_stattarget(), table_close(), and table_open().

Referenced by do_analyze_rel().

◆ dependencies_clauselist_selectivity()

Selectivity dependencies_clauselist_selectivity ( PlannerInfo root,
List clauses,
int  varRelid,
JoinType  jointype,
SpecialJoinInfo sjinfo,
RelOptInfo rel,
Bitmapset **  estimatedclauses 
)

Definition at line 1395 of file dependencies.c.

1402 {
1403  Selectivity s1 = 1.0;
1404  ListCell *l;
1405  Bitmapset *clauses_attnums = NULL;
1406  AttrNumber *list_attnums;
1407  int listidx;
1408  MVDependencies **func_dependencies;
1409  int nfunc_dependencies;
1410  int total_ndeps;
1411  MVDependency **dependencies;
1412  int ndependencies;
1413  int i;
1414  AttrNumber attnum_offset;
1415  RangeTblEntry *rte = planner_rt_fetch(rel->relid, root);
1416 
1417  /* unique expressions */
1418  Node **unique_exprs;
1419  int unique_exprs_cnt;
1420 
1421  /* check if there's any stats that might be useful for us. */
1422  if (!has_stats_of_kind(rel->statlist, STATS_EXT_DEPENDENCIES))
1423  return 1.0;
1424 
1425  list_attnums = (AttrNumber *) palloc(sizeof(AttrNumber) *
1426  list_length(clauses));
1427 
1428  /*
1429  * We allocate space as if every clause was a unique expression, although
1430  * that's probably overkill. Some will be simple column references that
1431  * we'll translate to attnums, and there might be duplicates. But it's
1432  * easier and cheaper to just do one allocation than repalloc later.
1433  */
1434  unique_exprs = (Node **) palloc(sizeof(Node *) * list_length(clauses));
1435  unique_exprs_cnt = 0;
1436 
1437  /*
1438  * Pre-process the clauses list to extract the attnums seen in each item.
1439  * We need to determine if there's any clauses which will be useful for
1440  * dependency selectivity estimations. Along the way we'll record all of
1441  * the attnums for each clause in a list which we'll reference later so we
1442  * don't need to repeat the same work again. We'll also keep track of all
1443  * attnums seen.
1444  *
1445  * We also skip clauses that we already estimated using different types of
1446  * statistics (we treat them as incompatible).
1447  *
1448  * To handle expressions, we assign them negative attnums, as if it was a
1449  * system attribute (this is fine, as we only allow extended stats on user
1450  * attributes). And then we offset everything by the number of
1451  * expressions, so that we can store the values in a bitmapset.
1452  */
1453  listidx = 0;
1454  foreach(l, clauses)
1455  {
1456  Node *clause = (Node *) lfirst(l);
1458  Node *expr = NULL;
1459 
1460  /* ignore clause by default */
1461  list_attnums[listidx] = InvalidAttrNumber;
1462 
1463  if (!bms_is_member(listidx, *estimatedclauses))
1464  {
1465  /*
1466  * If it's a simple column reference, just extract the attnum. If
1467  * it's an expression, assign a negative attnum as if it was a
1468  * system attribute.
1469  */
1470  if (dependency_is_compatible_clause(clause, rel->relid, &attnum))
1471  {
1472  list_attnums[listidx] = attnum;
1473  }
1474  else if (dependency_is_compatible_expression(clause, rel->relid,
1475  rel->statlist,
1476  &expr))
1477  {
1478  /* special attnum assigned to this expression */
1480 
1481  Assert(expr != NULL);
1482 
1483  /* If the expression is duplicate, use the same attnum. */
1484  for (i = 0; i < unique_exprs_cnt; i++)
1485  {
1486  if (equal(unique_exprs[i], expr))
1487  {
1488  /* negative attribute number to expression */
1489  attnum = -(i + 1);
1490  break;
1491  }
1492  }
1493 
1494  /* not found in the list, so add it */
1495  if (attnum == InvalidAttrNumber)
1496  {
1497  unique_exprs[unique_exprs_cnt++] = expr;
1498 
1499  /* after incrementing the value, to get -1, -2, ... */
1500  attnum = (-unique_exprs_cnt);
1501  }
1502 
1503  /* remember which attnum was assigned to this clause */
1504  list_attnums[listidx] = attnum;
1505  }
1506  }
1507 
1508  listidx++;
1509  }
1510 
1511  Assert(listidx == list_length(clauses));
1512 
1513  /*
1514  * How much we need to offset the attnums? If there are no expressions,
1515  * then no offset is needed. Otherwise we need to offset enough for the
1516  * lowest value (-unique_exprs_cnt) to become 1.
1517  */
1518  if (unique_exprs_cnt > 0)
1519  attnum_offset = (unique_exprs_cnt + 1);
1520  else
1521  attnum_offset = 0;
1522 
1523  /*
1524  * Now that we know how many expressions there are, we can offset the
1525  * values just enough to build the bitmapset.
1526  */
1527  for (i = 0; i < list_length(clauses); i++)
1528  {
1530 
1531  /* ignore incompatible or already estimated clauses */
1532  if (list_attnums[i] == InvalidAttrNumber)
1533  continue;
1534 
1535  /* make sure the attnum is in the expected range */
1536  Assert(list_attnums[i] >= (-unique_exprs_cnt));
1537  Assert(list_attnums[i] <= MaxHeapAttributeNumber);
1538 
1539  /* make sure the attnum is positive (valid AttrNumber) */
1540  attnum = list_attnums[i] + attnum_offset;
1541 
1542  /*
1543  * Either it's a regular attribute, or it's an expression, in which
1544  * case we must not have seen it before (expressions are unique).
1545  *
1546  * XXX Check whether it's a regular attribute has to be done using the
1547  * original attnum, while the second check has to use the value with
1548  * an offset.
1549  */
1550  Assert(AttrNumberIsForUserDefinedAttr(list_attnums[i]) ||
1551  !bms_is_member(attnum, clauses_attnums));
1552 
1553  /*
1554  * Remember the offset attnum, both for attributes and expressions.
1555  * We'll pass list_attnums to clauselist_apply_dependencies, which
1556  * uses it to identify clauses in a bitmap. We could also pass the
1557  * offset, but this is more convenient.
1558  */
1559  list_attnums[i] = attnum;
1560 
1561  clauses_attnums = bms_add_member(clauses_attnums, attnum);
1562  }
1563 
1564  /*
1565  * If there's not at least two distinct attnums and expressions, then
1566  * reject the whole list of clauses. We must return 1.0 so the calling
1567  * function's selectivity is unaffected.
1568  */
1569  if (bms_membership(clauses_attnums) != BMS_MULTIPLE)
1570  {
1571  bms_free(clauses_attnums);
1572  pfree(list_attnums);
1573  return 1.0;
1574  }
1575 
1576  /*
1577  * Load all functional dependencies matching at least two parameters. We
1578  * can simply consider all dependencies at once, without having to search
1579  * for the best statistics object.
1580  *
1581  * To not waste cycles and memory, we deserialize dependencies only for
1582  * statistics that match at least two attributes. The array is allocated
1583  * with the assumption that all objects match - we could grow the array to
1584  * make it just the right size, but it's likely wasteful anyway thanks to
1585  * moving the freed chunks to freelists etc.
1586  */
1587  func_dependencies = (MVDependencies **) palloc(sizeof(MVDependencies *) *
1588  list_length(rel->statlist));
1589  nfunc_dependencies = 0;
1590  total_ndeps = 0;
1591 
1592  foreach(l, rel->statlist)
1593  {
1595  int nmatched;
1596  int nexprs;
1597  int k;
1598  MVDependencies *deps;
1599 
1600  /* skip statistics that are not of the correct type */
1601  if (stat->kind != STATS_EXT_DEPENDENCIES)
1602  continue;
1603 
1604  /* skip statistics with mismatching stxdinherit value */
1605  if (stat->inherit != rte->inh)
1606  continue;
1607 
1608  /*
1609  * Count matching attributes - we have to undo the attnum offsets. The
1610  * input attribute numbers are not offset (expressions are not
1611  * included in stat->keys, so it's not necessary). But we need to
1612  * offset it before checking against clauses_attnums.
1613  */
1614  nmatched = 0;
1615  k = -1;
1616  while ((k = bms_next_member(stat->keys, k)) >= 0)
1617  {
1619 
1620  /* skip expressions */
1622  continue;
1623 
1624  /* apply the same offset as above */
1625  attnum += attnum_offset;
1626 
1627  if (bms_is_member(attnum, clauses_attnums))
1628  nmatched++;
1629  }
1630 
1631  /* count matching expressions */
1632  nexprs = 0;
1633  for (i = 0; i < unique_exprs_cnt; i++)
1634  {
1635  ListCell *lc;
1636 
1637  foreach(lc, stat->exprs)
1638  {
1639  Node *stat_expr = (Node *) lfirst(lc);
1640 
1641  /* try to match it */
1642  if (equal(stat_expr, unique_exprs[i]))
1643  nexprs++;
1644  }
1645  }
1646 
1647  /*
1648  * Skip objects matching fewer than two attributes/expressions from
1649  * clauses.
1650  */
1651  if (nmatched + nexprs < 2)
1652  continue;
1653 
1654  deps = statext_dependencies_load(stat->statOid, rte->inh);
1655 
1656  /*
1657  * The expressions may be represented by different attnums in the
1658  * stats, we need to remap them to be consistent with the clauses.
1659  * That will make the later steps (e.g. picking the strongest item and
1660  * so on) much simpler and cheaper, because it won't need to care
1661  * about the offset at all.
1662  *
1663  * When we're at it, we can ignore dependencies that are not fully
1664  * matched by clauses (i.e. referencing attributes or expressions that
1665  * are not in the clauses).
1666  *
1667  * We have to do this for all statistics, as long as there are any
1668  * expressions - we need to shift the attnums in all dependencies.
1669  *
1670  * XXX Maybe we should do this always, because it also eliminates some
1671  * of the dependencies early. It might be cheaper than having to walk
1672  * the longer list in find_strongest_dependency later, especially as
1673  * we need to do that repeatedly?
1674  *
1675  * XXX We have to do this even when there are no expressions in
1676  * clauses, otherwise find_strongest_dependency may fail for stats
1677  * with expressions (due to lookup of negative value in bitmap). So we
1678  * need to at least filter out those dependencies. Maybe we could do
1679  * it in a cheaper way (if there are no expr clauses, we can just
1680  * discard all negative attnums without any lookups).
1681  */
1682  if (unique_exprs_cnt > 0 || stat->exprs != NIL)
1683  {
1684  int ndeps = 0;
1685 
1686  for (i = 0; i < deps->ndeps; i++)
1687  {
1688  bool skip = false;
1689  MVDependency *dep = deps->deps[i];
1690  int j;
1691 
1692  for (j = 0; j < dep->nattributes; j++)
1693  {
1694  int idx;
1695  Node *expr;
1696  int k;
1697  AttrNumber unique_attnum = InvalidAttrNumber;
1699 
1700  /* undo the per-statistics offset */
1701  attnum = dep->attributes[j];
1702 
1703  /*
1704  * For regular attributes we can simply check if it
1705  * matches any clause. If there's no matching clause, we
1706  * can just ignore it. We need to offset the attnum
1707  * though.
1708  */
1710  {
1711  dep->attributes[j] = attnum + attnum_offset;
1712 
1713  if (!bms_is_member(dep->attributes[j], clauses_attnums))
1714  {
1715  skip = true;
1716  break;
1717  }
1718 
1719  continue;
1720  }
1721 
1722  /*
1723  * the attnum should be a valid system attnum (-1, -2,
1724  * ...)
1725  */
1727 
1728  /*
1729  * For expressions, we need to do two translations. First
1730  * we have to translate the negative attnum to index in
1731  * the list of expressions (in the statistics object).
1732  * Then we need to see if there's a matching clause. The
1733  * index of the unique expression determines the attnum
1734  * (and we offset it).
1735  */
1736  idx = -(1 + attnum);
1737 
1738  /* Is the expression index is valid? */
1739  Assert((idx >= 0) && (idx < list_length(stat->exprs)));
1740 
1741  expr = (Node *) list_nth(stat->exprs, idx);
1742 
1743  /* try to find the expression in the unique list */
1744  for (k = 0; k < unique_exprs_cnt; k++)
1745  {
1746  /*
1747  * found a matching unique expression, use the attnum
1748  * (derived from index of the unique expression)
1749  */
1750  if (equal(unique_exprs[k], expr))
1751  {
1752  unique_attnum = -(k + 1) + attnum_offset;
1753  break;
1754  }
1755  }
1756 
1757  /*
1758  * Found no matching expression, so we can simply skip
1759  * this dependency, because there's no chance it will be
1760  * fully covered.
1761  */
1762  if (unique_attnum == InvalidAttrNumber)
1763  {
1764  skip = true;
1765  break;
1766  }
1767 
1768  /* otherwise remap it to the new attnum */
1769  dep->attributes[j] = unique_attnum;
1770  }
1771 
1772  /* if found a matching dependency, keep it */
1773  if (!skip)
1774  {
1775  /* maybe we've skipped something earlier, so move it */
1776  if (ndeps != i)
1777  deps->deps[ndeps] = deps->deps[i];
1778 
1779  ndeps++;
1780  }
1781  }
1782 
1783  deps->ndeps = ndeps;
1784  }
1785 
1786  /*
1787  * It's possible we've removed all dependencies, in which case we
1788  * don't bother adding it to the list.
1789  */
1790  if (deps->ndeps > 0)
1791  {
1792  func_dependencies[nfunc_dependencies] = deps;
1793  total_ndeps += deps->ndeps;
1794  nfunc_dependencies++;
1795  }
1796  }
1797 
1798  /* if no matching stats could be found then we've nothing to do */
1799  if (nfunc_dependencies == 0)
1800  {
1801  pfree(func_dependencies);
1802  bms_free(clauses_attnums);
1803  pfree(list_attnums);
1804  pfree(unique_exprs);
1805  return 1.0;
1806  }
1807 
1808  /*
1809  * Work out which dependencies we can apply, starting with the
1810  * widest/strongest ones, and proceeding to smaller/weaker ones.
1811  */
1812  dependencies = (MVDependency **) palloc(sizeof(MVDependency *) *
1813  total_ndeps);
1814  ndependencies = 0;
1815 
1816  while (true)
1817  {
1818  MVDependency *dependency;
1820 
1821  /* the widest/strongest dependency, fully matched by clauses */
1822  dependency = find_strongest_dependency(func_dependencies,
1823  nfunc_dependencies,
1824  clauses_attnums);
1825  if (!dependency)
1826  break;
1827 
1828  dependencies[ndependencies++] = dependency;
1829 
1830  /* Ignore dependencies using this implied attribute in later loops */
1831  attnum = dependency->attributes[dependency->nattributes - 1];
1832  clauses_attnums = bms_del_member(clauses_attnums, attnum);
1833  }
1834 
1835  /*
1836  * If we found applicable dependencies, use them to estimate all
1837  * compatible clauses on attributes that they refer to.
1838  */
1839  if (ndependencies != 0)
1840  s1 = clauselist_apply_dependencies(root, clauses, varRelid, jointype,
1841  sjinfo, dependencies, ndependencies,
1842  list_attnums, estimatedclauses);
1843 
1844  /* free deserialized functional dependencies (and then the array) */
1845  for (i = 0; i < nfunc_dependencies; i++)
1846  pfree(func_dependencies[i]);
1847 
1848  pfree(dependencies);
1849  pfree(func_dependencies);
1850  bms_free(clauses_attnums);
1851  pfree(list_attnums);
1852  pfree(unique_exprs);
1853 
1854  return s1;
1855 }
Datum idx(PG_FUNCTION_ARGS)
Definition: _int_op.c:259
int16 AttrNumber
Definition: attnum.h:21
#define AttributeNumberIsValid(attributeNumber)
Definition: attnum.h:34
#define AttrNumberIsForUserDefinedAttr(attributeNumber)
Definition: attnum.h:41
#define InvalidAttrNumber
Definition: attnum.h:23
int bms_next_member(const Bitmapset *a, int prevbit)
Definition: bitmapset.c:1045
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:427
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:738
Bitmapset * bms_del_member(Bitmapset *a, int x)
Definition: bitmapset.c:775
BMS_Membership bms_membership(const Bitmapset *a)
Definition: bitmapset.c:674
@ BMS_MULTIPLE
Definition: bitmapset.h:70
static bool dependency_is_compatible_expression(Node *clause, Index relid, List *statlist, Node **expr)
static bool dependency_is_compatible_clause(Node *clause, Index relid, AttrNumber *attnum)
Definition: dependencies.c:743
MVDependencies * statext_dependencies_load(Oid mvoid, bool inh)
Definition: dependencies.c:621
static Selectivity clauselist_apply_dependencies(PlannerInfo *root, List *clauses, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo, MVDependency **dependencies, int ndependencies, AttrNumber *list_attnums, Bitmapset **estimatedclauses)
static MVDependency * find_strongest_dependency(MVDependencies **dependencies, int ndependencies, Bitmapset *attnums)
Definition: dependencies.c:931
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:3564
bool has_stats_of_kind(List *stats, char requiredkind)
#define MaxHeapAttributeNumber
Definition: htup_details.h:47
int j
Definition: isn.c:74
Assert(fmt[strlen(fmt) - 1] !='\n')
void pfree(void *pointer)
Definition: mcxt.c:1175
void * palloc(Size size)
Definition: mcxt.c:1068
double Selectivity
Definition: nodes.h:706
#define planner_rt_fetch(rti, root)
Definition: pathnodes.h:389
int16 attnum
Definition: pg_attribute.h:83
static const struct exclude_list_item skip[]
Definition: pg_checksums.c:116
static void * list_nth(const List *list, int n)
Definition: pg_list.h:278
char * s1
uint32 ndeps
Definition: statistics.h:61
MVDependency * deps[FLEXIBLE_ARRAY_MEMBER]
Definition: statistics.h:62
AttrNumber nattributes
Definition: statistics.h:53
AttrNumber attributes[FLEXIBLE_ARRAY_MEMBER]
Definition: statistics.h:54
Definition: nodes.h:574
Index relid
Definition: pathnodes.h:710
List * statlist
Definition: pathnodes.h:720

References Assert(), attnum, AttributeNumberIsValid, MVDependency::attributes, AttrNumberIsForUserDefinedAttr, bms_add_member(), bms_del_member(), bms_free(), bms_is_member(), bms_membership(), BMS_MULTIPLE, bms_next_member(), clauselist_apply_dependencies(), dependency_is_compatible_clause(), dependency_is_compatible_expression(), MVDependencies::deps, equal(), find_strongest_dependency(), has_stats_of_kind(), i, idx(), RangeTblEntry::inh, InvalidAttrNumber, j, lfirst, list_length(), list_nth(), MaxHeapAttributeNumber, MVDependency::nattributes, MVDependencies::ndeps, NIL, palloc(), pfree(), planner_rt_fetch, RelOptInfo::relid, s1, skip, statext_dependencies_load(), and RelOptInfo::statlist.

Referenced by statext_clauselist_selectivity().

◆ has_stats_of_kind()

bool has_stats_of_kind ( List stats,
char  requiredkind 
)

Definition at line 1143 of file extended_stats.c.

1144 {
1145  ListCell *l;
1146 
1147  foreach(l, stats)
1148  {
1150 
1151  if (stat->kind == requiredkind)
1152  return true;
1153  }
1154 
1155  return false;
1156 }

References lfirst.

Referenced by dependencies_clauselist_selectivity(), and statext_mcv_clauselist_selectivity().

◆ statext_clauselist_selectivity()

Selectivity statext_clauselist_selectivity ( PlannerInfo root,
List clauses,
int  varRelid,
JoinType  jointype,
SpecialJoinInfo sjinfo,
RelOptInfo rel,
Bitmapset **  estimatedclauses,
bool  is_or 
)

Definition at line 1976 of file extended_stats.c.

1980 {
1981  Selectivity sel;
1982 
1983  /* First, try estimating clauses using a multivariate MCV list. */
1984  sel = statext_mcv_clauselist_selectivity(root, clauses, varRelid, jointype,
1985  sjinfo, rel, estimatedclauses, is_or);
1986 
1987  /*
1988  * Functional dependencies only work for clauses connected by AND, so for
1989  * OR clauses we're done.
1990  */
1991  if (is_or)
1992  return sel;
1993 
1994  /*
1995  * Then, apply functional dependencies on the remaining clauses by calling
1996  * dependencies_clauselist_selectivity. Pass 'estimatedclauses' so the
1997  * function can properly skip clauses already estimated above.
1998  *
1999  * The reasoning for applying dependencies last is that the more complex
2000  * stats can track more complex correlations between the attributes, and
2001  * so may be considered more reliable.
2002  *
2003  * For example, MCV list can give us an exact selectivity for values in
2004  * two columns, while functional dependencies can only provide information
2005  * about the overall strength of the dependency.
2006  */
2007  sel *= dependencies_clauselist_selectivity(root, clauses, varRelid,
2008  jointype, sjinfo, rel,
2009  estimatedclauses);
2010 
2011  return sel;
2012 }
Selectivity dependencies_clauselist_selectivity(PlannerInfo *root, List *clauses, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo, RelOptInfo *rel, Bitmapset **estimatedclauses)
static Selectivity statext_mcv_clauselist_selectivity(PlannerInfo *root, List *clauses, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo, RelOptInfo *rel, Bitmapset **estimatedclauses, bool is_or)

References dependencies_clauselist_selectivity(), and statext_mcv_clauselist_selectivity().

Referenced by clauselist_selectivity_ext(), and clauselist_selectivity_or().

◆ statext_dependencies_load()

MVDependencies* statext_dependencies_load ( Oid  mvoid,
bool  inh 
)

Definition at line 621 of file dependencies.c.

622 {
623  MVDependencies *result;
624  bool isnull;
625  Datum deps;
626  HeapTuple htup;
627 
629  ObjectIdGetDatum(mvoid),
630  BoolGetDatum(inh));
631  if (!HeapTupleIsValid(htup))
632  elog(ERROR, "cache lookup failed for statistics object %u", mvoid);
633 
634  deps = SysCacheGetAttr(STATEXTDATASTXOID, htup,
635  Anum_pg_statistic_ext_data_stxddependencies, &isnull);
636  if (isnull)
637  elog(ERROR,
638  "requested statistics kind \"%c\" is not yet built for statistics object %u",
639  STATS_EXT_DEPENDENCIES, mvoid);
640 
642 
643  ReleaseSysCache(htup);
644 
645  return result;
646 }
MVDependencies * statext_dependencies_deserialize(bytea *data)
Definition: dependencies.c:501
#define DatumGetByteaPP(X)
Definition: fmgr.h:291
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define BoolGetDatum(X)
Definition: postgres.h:446
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1221
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1434
HeapTuple SearchSysCache2(int cacheId, Datum key1, Datum key2)
Definition: syscache.c:1184
@ STATEXTDATASTXOID
Definition: syscache.h:94

References BoolGetDatum, DatumGetByteaPP, elog, ERROR, HeapTupleIsValid, ObjectIdGetDatum, ReleaseSysCache(), SearchSysCache2(), statext_dependencies_deserialize(), STATEXTDATASTXOID, and SysCacheGetAttr().

Referenced by dependencies_clauselist_selectivity().

◆ statext_expressions_load()

HeapTuple statext_expressions_load ( Oid  stxoid,
bool  inh,
int  idx 
)

Definition at line 2401 of file extended_stats.c.

2402 {
2403  bool isnull;
2404  Datum value;
2405  HeapTuple htup;
2406  ExpandedArrayHeader *eah;
2407  HeapTupleHeader td;
2408  HeapTupleData tmptup;
2409  HeapTuple tup;
2410 
2412  ObjectIdGetDatum(stxoid), BoolGetDatum(inh));
2413  if (!HeapTupleIsValid(htup))
2414  elog(ERROR, "cache lookup failed for statistics object %u", stxoid);
2415 
2417  Anum_pg_statistic_ext_data_stxdexpr, &isnull);
2418  if (isnull)
2419  elog(ERROR,
2420  "requested statistics kind \"%c\" is not yet built for statistics object %u",
2421  STATS_EXT_DEPENDENCIES, stxoid);
2422 
2424 
2426 
2427  td = DatumGetHeapTupleHeader(eah->dvalues[idx]);
2428 
2429  /* Build a temporary HeapTuple control structure */
2430  tmptup.t_len = HeapTupleHeaderGetDatumLength(td);
2431  ItemPointerSetInvalid(&(tmptup.t_self));
2432  tmptup.t_tableOid = InvalidOid;
2433  tmptup.t_data = td;
2434 
2435  tup = heap_copytuple(&tmptup);
2436 
2437  ReleaseSysCache(htup);
2438 
2439  return tup;
2440 }
ExpandedArrayHeader * DatumGetExpandedArray(Datum d)
void deconstruct_expanded_array(ExpandedArrayHeader *eah)
#define DatumGetHeapTupleHeader(X)
Definition: fmgr.h:295
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:680
#define HeapTupleHeaderGetDatumLength(tup)
Definition: htup_details.h:446
static struct @151 value
#define ItemPointerSetInvalid(pointer)
Definition: itemptr.h:172
#define InvalidOid
Definition: postgres_ext.h:36
Datum * dvalues
Definition: array.h:139
ItemPointerData t_self
Definition: htup.h:65
uint32 t_len
Definition: htup.h:64
HeapTupleHeader t_data
Definition: htup.h:68
Oid t_tableOid
Definition: htup.h:66

References BoolGetDatum, DatumGetExpandedArray(), DatumGetHeapTupleHeader, deconstruct_expanded_array(), ExpandedArrayHeader::dvalues, elog, ERROR, heap_copytuple(), HeapTupleHeaderGetDatumLength, HeapTupleIsValid, idx(), InvalidOid, ItemPointerSetInvalid, ObjectIdGetDatum, ReleaseSysCache(), SearchSysCache2(), STATEXTDATASTXOID, SysCacheGetAttr(), HeapTupleData::t_data, HeapTupleData::t_len, HeapTupleData::t_self, HeapTupleData::t_tableOid, and value.

Referenced by examine_variable().

◆ statext_is_kind_built()

bool statext_is_kind_built ( HeapTuple  htup,
char  kind 
)

Definition at line 392 of file extended_stats.c.

393 {
395 
396  switch (type)
397  {
398  case STATS_EXT_NDISTINCT:
399  attnum = Anum_pg_statistic_ext_data_stxdndistinct;
400  break;
401 
402  case STATS_EXT_DEPENDENCIES:
403  attnum = Anum_pg_statistic_ext_data_stxddependencies;
404  break;
405 
406  case STATS_EXT_MCV:
407  attnum = Anum_pg_statistic_ext_data_stxdmcv;
408  break;
409 
410  case STATS_EXT_EXPRESSIONS:
411  attnum = Anum_pg_statistic_ext_data_stxdexpr;
412  break;
413 
414  default:
415  elog(ERROR, "unexpected statistics type requested: %d", type);
416  }
417 
418  return !heap_attisnull(htup, attnum, NULL);
419 }
bool heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc)
Definition: heaptuple.c:359

References attnum, elog, ERROR, heap_attisnull(), and generate_unaccent_rules::type.

Referenced by get_relation_statistics_worker().

◆ statext_mcv_load()

MCVList* statext_mcv_load ( Oid  mvoid,
bool  inh 
)

Definition at line 562 of file mcv.c.

563 {
564  MCVList *result;
565  bool isnull;
566  Datum mcvlist;
568  ObjectIdGetDatum(mvoid), BoolGetDatum(inh));
569 
570  if (!HeapTupleIsValid(htup))
571  elog(ERROR, "cache lookup failed for statistics object %u", mvoid);
572 
573  mcvlist = SysCacheGetAttr(STATEXTDATASTXOID, htup,
574  Anum_pg_statistic_ext_data_stxdmcv, &isnull);
575 
576  if (isnull)
577  elog(ERROR,
578  "requested statistics kind \"%c\" is not yet built for statistics object %u",
579  STATS_EXT_DEPENDENCIES, mvoid);
580 
581  result = statext_mcv_deserialize(DatumGetByteaP(mcvlist));
582 
583  ReleaseSysCache(htup);
584 
585  return result;
586 }
#define DatumGetByteaP(X)
Definition: fmgr.h:331
MCVList * statext_mcv_deserialize(bytea *data)
Definition: mcv.c:1000

References BoolGetDatum, DatumGetByteaP, elog, ERROR, HeapTupleIsValid, ObjectIdGetDatum, ReleaseSysCache(), SearchSysCache2(), statext_mcv_deserialize(), STATEXTDATASTXOID, and SysCacheGetAttr().

Referenced by mcv_clauselist_selectivity(), and statext_mcv_clauselist_selectivity().

◆ statext_ndistinct_load()

MVNDistinct* statext_ndistinct_load ( Oid  mvoid,
bool  inh 
)

Definition at line 149 of file mvdistinct.c.

150 {
151  MVNDistinct *result;
152  bool isnull;
153  Datum ndist;
154  HeapTuple htup;
155 
157  ObjectIdGetDatum(mvoid), BoolGetDatum(inh));
158  if (!HeapTupleIsValid(htup))
159  elog(ERROR, "cache lookup failed for statistics object %u", mvoid);
160 
161  ndist = SysCacheGetAttr(STATEXTDATASTXOID, htup,
162  Anum_pg_statistic_ext_data_stxdndistinct, &isnull);
163  if (isnull)
164  elog(ERROR,
165  "requested statistics kind \"%c\" is not yet built for statistics object %u",
166  STATS_EXT_NDISTINCT, mvoid);
167 
169 
170  ReleaseSysCache(htup);
171 
172  return result;
173 }
MVNDistinct * statext_ndistinct_deserialize(bytea *data)
Definition: mvdistinct.c:251

References BoolGetDatum, DatumGetByteaPP, elog, ERROR, HeapTupleIsValid, ObjectIdGetDatum, ReleaseSysCache(), SearchSysCache2(), statext_ndistinct_deserialize(), STATEXTDATASTXOID, and SysCacheGetAttr().

Referenced by estimate_multivariate_ndistinct().