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 **vacattrstats)
 
bool statext_is_kind_built (HeapTuple htup, char type)
 
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:3314
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:649
MVDependencies * statext_dependencies_build(StatsBuildData *data)
Definition: dependencies.c:350
int errcode(int sqlerrcode)
Definition: elog.c:695
int errmsg(const char *fmt,...)
Definition: elog.c:906
#define WARNING
Definition: elog.h:32
#define ERROR
Definition: elog.h:35
#define ereport(elevel,...)
Definition: elog.h:145
static AnlExprData * build_expr_data(List *exprs, int stattarget)
static StatsBuildData * make_build_data(Relation rel, StatExtEntry *stat, int numrows, HeapTuple *rows, VacAttrStats **stats, 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 int statext_compute_stattarget(int stattarget, int nattrs, VacAttrStats **stats)
static Datum serialize_expr_stats(AnlExprData *exprdata, int nexprs)
long val
Definition: informix.c:664
void list_free(List *list)
Definition: list.c:1545
#define RowExclusiveLock
Definition: lockdefs.h:38
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3331
MCVList * statext_mcv_build(StatsBuildData *data, double totalrows, int stattarget)
Definition: mcv.c:184
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:303
MemoryContext CurrentMemoryContext
Definition: mcxt.c:124
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:376
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:153
MVNDistinct * statext_ndistinct_build(double totalrows, StatsBuildData *data)
Definition: mvdistinct.c:89
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:135
const void * data
#define lfirst(lc)
Definition: pg_list.h:170
static int list_length(const List *l)
Definition: pg_list.h:150
#define NIL
Definition: pg_list.h:66
#define lfirst_int(lc)
Definition: pg_list.h:171
uintptr_t Datum
Definition: postgres.h:412
#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:501
#define RelationGetRelationName(relation)
Definition: rel.h:535
int errtable(Relation rel)
Definition: relcache.c:5876
Definition: pg_list.h:52
Form_pg_class rd_rel
Definition: rel.h:110
Definition: type.h:95
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:40

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:316
void bms_free(Bitmapset *a)
Definition: bitmapset.c:209
Bitmapset * bms_add_members(Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:796
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:1237

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 **  vacattrstats 
)

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 1394 of file dependencies.c.

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

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 2029 of file extended_stats.c.

2033 {
2034  Selectivity sel;
2035 
2036  /* First, try estimating clauses using a multivariate MCV list. */
2037  sel = statext_mcv_clauselist_selectivity(root, clauses, varRelid, jointype,
2038  sjinfo, rel, estimatedclauses, is_or);
2039 
2040  /*
2041  * Functional dependencies only work for clauses connected by AND, so for
2042  * OR clauses we're done.
2043  */
2044  if (is_or)
2045  return sel;
2046 
2047  /*
2048  * Then, apply functional dependencies on the remaining clauses by calling
2049  * dependencies_clauselist_selectivity. Pass 'estimatedclauses' so the
2050  * function can properly skip clauses already estimated above.
2051  *
2052  * The reasoning for applying dependencies last is that the more complex
2053  * stats can track more complex correlations between the attributes, and
2054  * so may be considered more reliable.
2055  *
2056  * For example, MCV list can give us an exact selectivity for values in
2057  * two columns, while functional dependencies can only provide information
2058  * about the overall strength of the dependency.
2059  */
2060  sel *= dependencies_clauselist_selectivity(root, clauses, varRelid,
2061  jointype, sjinfo, rel,
2062  estimatedclauses);
2063 
2064  return sel;
2065 }
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
static Datum BoolGetDatum(bool X)
Definition: postgres.h:450
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:600
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 2451 of file extended_stats.c.

2452 {
2453  bool isnull;
2454  Datum value;
2455  HeapTuple htup;
2456  ExpandedArrayHeader *eah;
2457  HeapTupleHeader td;
2458  HeapTupleData tmptup;
2459  HeapTuple tup;
2460 
2462  ObjectIdGetDatum(stxoid), BoolGetDatum(inh));
2463  if (!HeapTupleIsValid(htup))
2464  elog(ERROR, "cache lookup failed for statistics object %u", stxoid);
2465 
2467  Anum_pg_statistic_ext_data_stxdexpr, &isnull);
2468  if (isnull)
2469  elog(ERROR,
2470  "requested statistics kind \"%c\" is not yet built for statistics object %u",
2471  STATS_EXT_DEPENDENCIES, stxoid);
2472 
2474 
2476 
2477  td = DatumGetHeapTupleHeader(eah->dvalues[idx]);
2478 
2479  /* Build a temporary HeapTuple control structure */
2480  tmptup.t_len = HeapTupleHeaderGetDatumLength(td);
2481  ItemPointerSetInvalid(&(tmptup.t_self));
2482  tmptup.t_tableOid = InvalidOid;
2483  tmptup.t_data = td;
2484 
2485  tup = heap_copytuple(&tmptup);
2486 
2487  ReleaseSysCache(htup);
2488 
2489  return tup;
2490 }
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 @143 value
static void ItemPointerSetInvalid(ItemPointerData *pointer)
Definition: itemptr.h:184
#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  type 
)

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().