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)
 
MVDependenciesstatext_dependencies_load (Oid mvoid)
 
MCVListstatext_mcv_load (Oid mvoid)
 
void BuildRelationExtStatistics (Relation onerel, 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, Bitmapset **clause_attnums, List **clause_exprs, int nclauses)
 
HeapTuple statext_expressions_load (Oid stxoid, int idx)
 

Macro Definition Documentation

◆ STATS_DEPS_MAGIC

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

Definition at line 43 of file statistics.h.

Referenced by statext_dependencies_build(), and statext_dependencies_deserialize().

◆ STATS_DEPS_TYPE_BASIC

#define STATS_DEPS_TYPE_BASIC   1 /* basic dependencies type */

Definition at line 44 of file statistics.h.

Referenced by statext_dependencies_build(), and statext_dependencies_deserialize().

◆ STATS_MAX_DIMENSIONS

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

◆ STATS_MCV_MAGIC

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

Definition at line 66 of file statistics.h.

Referenced by statext_mcv_build(), and statext_mcv_deserialize().

◆ STATS_MCV_TYPE_BASIC

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

Definition at line 67 of file statistics.h.

Referenced by statext_mcv_build(), and statext_mcv_deserialize().

◆ STATS_MCVLIST_MAX_ITEMS

#define STATS_MCVLIST_MAX_ITEMS   10000

Definition at line 70 of file statistics.h.

Referenced by mcv_get_match_bitmap(), and statext_mcv_deserialize().

◆ STATS_NDISTINCT_MAGIC

#define STATS_NDISTINCT_MAGIC   0xA352BFA4 /* struct identifier */

◆ STATS_NDISTINCT_TYPE_BASIC

#define STATS_NDISTINCT_TYPE_BASIC   1 /* struct version */

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,
double  totalrows,
int  numrows,
HeapTuple rows,
int  natts,
VacAttrStats **  vacattrstats 
)

Definition at line 113 of file extended_stats.c.

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, bms_num_members(), build_expr_data(), StatExtEntry::columns, compute_expr_stats(), CurrentMemoryContext, elog, ereport, errcode(), errmsg(), ERROR, errtable(), StatExtEntry::exprs, fetch_statentries_for_relation(), get_namespace_name(), IsAutoVacuumWorkerProcess(), lfirst, lfirst_int, list_length(), lookup_var_attr_stats(), make_build_data(), MemoryContextDelete(), MemoryContextSwitchTo(), StatExtEntry::name, NIL, pfree(), 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, StatExtEntry::schema, serialize_expr_stats(), statext_compute_stattarget(), statext_dependencies_build(), statext_mcv_build(), statext_ndistinct_build(), statext_store(), StatExtEntry::statOid, StatExtEntry::stattarget, table_close(), table_open(), StatExtEntry::types, val, and WARNING.

Referenced by do_analyze_rel().

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

◆ choose_best_statistics()

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

Definition at line 1233 of file extended_stats.c.

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

Referenced by statext_mcv_clauselist_selectivity().

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

◆ ComputeExtStatisticsRows()

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

Definition at line 261 of file extended_stats.c.

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

Referenced by do_analyze_rel().

263 {
264  Relation pg_stext;
265  ListCell *lc;
266  List *lstats;
267  MemoryContext cxt;
268  MemoryContext oldcxt;
269  int result = 0;
270 
271  /* If there are no columns to analyze, just return 0. */
272  if (!natts)
273  return 0;
274 
276  "ComputeExtStatisticsRows",
278  oldcxt = MemoryContextSwitchTo(cxt);
279 
280  pg_stext = table_open(StatisticExtRelationId, RowExclusiveLock);
281  lstats = fetch_statentries_for_relation(pg_stext, RelationGetRelid(onerel));
282 
283  foreach(lc, lstats)
284  {
286  int stattarget;
287  VacAttrStats **stats;
288  int nattrs = bms_num_members(stat->columns);
289 
290  /*
291  * Check if we can build this statistics object based on the columns
292  * analyzed. If not, ignore it (don't report anything, we'll do that
293  * during the actual build BuildRelationExtStatistics).
294  */
295  stats = lookup_var_attr_stats(onerel, stat->columns, stat->exprs,
296  natts, vacattrstats);
297 
298  if (!stats)
299  continue;
300 
301  /*
302  * Compute statistics target, based on what's set for the statistic
303  * object itself, and for its attributes.
304  */
305  stattarget = statext_compute_stattarget(stat->stattarget,
306  nattrs, stats);
307 
308  /* Use the largest value for all statistics objects. */
309  if (stattarget > result)
310  result = stattarget;
311  }
312 
313  table_close(pg_stext, RowExclusiveLock);
314 
315  MemoryContextSwitchTo(oldcxt);
316  MemoryContextDelete(cxt);
317 
318  /* compute sample size based on the statistics target */
319  return (300 * result);
320 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:218
#define AllocSetContextCreate
Definition: memutils.h:173
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
static int statext_compute_stattarget(int stattarget, int natts, VacAttrStats **stats)
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
static List * fetch_statentries_for_relation(Relation pg_statext, Oid relid)
Bitmapset * columns
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:195
int bms_num_members(const Bitmapset *a)
Definition: bitmapset.c:646
#define RowExclusiveLock
Definition: lockdefs.h:38
MemoryContext CurrentMemoryContext
Definition: mcxt.c:42
#define lfirst(lc)
Definition: pg_list.h:169
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
Definition: pg_list.h:50
#define RelationGetRelid(relation)
Definition: rel.h:457
static VacAttrStats ** lookup_var_attr_stats(Relation rel, Bitmapset *attrs, List *exprs, int nvacatts, VacAttrStats **vacatts)

◆ dependencies_clauselist_selectivity()

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

Definition at line 1383 of file dependencies.c.

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(), DependencyGeneratorData::dependencies, dependency_is_compatible_clause(), dependency_is_compatible_expression(), MVDependencies::deps, equal(), StatisticExtInfo::exprs, find_strongest_dependency(), has_stats_of_kind(), i, idx(), InvalidAttrNumber, DependencyGeneratorData::k, StatisticExtInfo::keys, StatisticExtInfo::kind, lfirst, list_length(), list_nth(), MaxHeapAttributeNumber, MVDependency::nattributes, DependencyGeneratorData::ndependencies, MVDependencies::ndeps, NIL, palloc(), pfree(), RelOptInfo::relid, s1, skip, statext_dependencies_load(), RelOptInfo::statlist, and StatisticExtInfo::statOid.

Referenced by statext_clauselist_selectivity().

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

◆ has_stats_of_kind()

bool has_stats_of_kind ( List stats,
char  requiredkind 
)

Definition at line 1142 of file extended_stats.c.

References StatisticExtInfo::kind, and lfirst.

Referenced by dependencies_clauselist_selectivity(), and statext_mcv_clauselist_selectivity().

1143 {
1144  ListCell *l;
1145 
1146  foreach(l, stats)
1147  {
1149 
1150  if (stat->kind == requiredkind)
1151  return true;
1152  }
1153 
1154  return false;
1155 }
#define lfirst(lc)
Definition: pg_list.h:169
int l
Definition: api.h:16

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

References dependencies_clauselist_selectivity(), and statext_mcv_clauselist_selectivity().

Referenced by clauselist_selectivity_ext(), and clauselist_selectivity_or().

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

◆ statext_dependencies_load()

MVDependencies* statext_dependencies_load ( Oid  mvoid)

Definition at line 611 of file dependencies.c.

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

Referenced by dependencies_clauselist_selectivity().

612 {
613  MVDependencies *result;
614  bool isnull;
615  Datum deps;
616  HeapTuple htup;
617 
619  if (!HeapTupleIsValid(htup))
620  elog(ERROR, "cache lookup failed for statistics object %u", mvoid);
621 
622  deps = SysCacheGetAttr(STATEXTDATASTXOID, htup,
623  Anum_pg_statistic_ext_data_stxddependencies, &isnull);
624  if (isnull)
625  elog(ERROR,
626  "requested statistics kind \"%c\" is not yet built for statistics object %u",
627  STATS_EXT_DEPENDENCIES, mvoid);
628 
630 
631  ReleaseSysCache(htup);
632 
633  return result;
634 }
#define DatumGetByteaPP(X)
Definition: fmgr.h:291
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
uintptr_t Datum
Definition: postgres.h:411
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1388
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define elog(elevel,...)
Definition: elog.h:232
MVDependencies * statext_dependencies_deserialize(bytea *data)
Definition: dependencies.c:491

◆ statext_expressions_load()

HeapTuple statext_expressions_load ( Oid  stxoid,
int  idx 
)

Definition at line 2394 of file extended_stats.c.

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

Referenced by examine_variable().

2395 {
2396  bool isnull;
2397  Datum value;
2398  HeapTuple htup;
2399  ExpandedArrayHeader *eah;
2400  HeapTupleHeader td;
2401  HeapTupleData tmptup;
2402  HeapTuple tup;
2403 
2405  if (!HeapTupleIsValid(htup))
2406  elog(ERROR, "cache lookup failed for statistics object %u", stxoid);
2407 
2408  value = SysCacheGetAttr(STATEXTDATASTXOID, htup,
2409  Anum_pg_statistic_ext_data_stxdexpr, &isnull);
2410  if (isnull)
2411  elog(ERROR,
2412  "requested statistics kind \"%c\" is not yet built for statistics object %u",
2413  STATS_EXT_DEPENDENCIES, stxoid);
2414 
2415  eah = DatumGetExpandedArray(value);
2416 
2418 
2419  td = DatumGetHeapTupleHeader(eah->dvalues[idx]);
2420 
2421  /* Build a temporary HeapTuple control structure */
2422  tmptup.t_len = HeapTupleHeaderGetDatumLength(td);
2423  ItemPointerSetInvalid(&(tmptup.t_self));
2424  tmptup.t_tableOid = InvalidOid;
2425  tmptup.t_data = td;
2426 
2427  tup = heap_copytuple(&tmptup);
2428 
2429  ReleaseSysCache(htup);
2430 
2431  return tup;
2432 }
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:680
void deconstruct_expanded_array(ExpandedArrayHeader *eah)
static struct @142 value
Datum idx(PG_FUNCTION_ARGS)
Definition: _int_op.c:259
Datum * dvalues
Definition: array.h:139
#define DatumGetHeapTupleHeader(X)
Definition: fmgr.h:295
HeapTupleHeader t_data
Definition: htup.h:68
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
ExpandedArrayHeader * DatumGetExpandedArray(Datum d)
ItemPointerData t_self
Definition: htup.h:65
uint32 t_len
Definition: htup.h:64
Oid t_tableOid
Definition: htup.h:66
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
uintptr_t Datum
Definition: postgres.h:411
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1388
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define ItemPointerSetInvalid(pointer)
Definition: itemptr.h:172
#define elog(elevel,...)
Definition: elog.h:232
#define HeapTupleHeaderGetDatumLength(tup)
Definition: htup_details.h:451

◆ statext_is_kind_built()

bool statext_is_kind_built ( HeapTuple  htup,
char  kind 
)

Definition at line 385 of file extended_stats.c.

References attnum, elog, ERROR, and heap_attisnull().

Referenced by get_relation_statistics().

386 {
388 
389  switch (type)
390  {
391  case STATS_EXT_NDISTINCT:
392  attnum = Anum_pg_statistic_ext_data_stxdndistinct;
393  break;
394 
395  case STATS_EXT_DEPENDENCIES:
396  attnum = Anum_pg_statistic_ext_data_stxddependencies;
397  break;
398 
399  case STATS_EXT_MCV:
400  attnum = Anum_pg_statistic_ext_data_stxdmcv;
401  break;
402 
403  case STATS_EXT_EXPRESSIONS:
404  attnum = Anum_pg_statistic_ext_data_stxdexpr;
405  break;
406 
407  default:
408  elog(ERROR, "unexpected statistics type requested: %d", type);
409  }
410 
411  return !heap_attisnull(htup, attnum, NULL);
412 }
bool heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc)
Definition: heaptuple.c:359
#define ERROR
Definition: elog.h:46
int16 attnum
Definition: pg_attribute.h:83
#define elog(elevel,...)
Definition: elog.h:232
int16 AttrNumber
Definition: attnum.h:21

◆ statext_mcv_load()

MCVList* statext_mcv_load ( Oid  mvoid)

Definition at line 560 of file mcv.c.

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

Referenced by mcv_clauselist_selectivity(), and statext_mcv_clauselist_selectivity().

561 {
562  MCVList *result;
563  bool isnull;
564  Datum mcvlist;
566 
567  if (!HeapTupleIsValid(htup))
568  elog(ERROR, "cache lookup failed for statistics object %u", mvoid);
569 
570  mcvlist = SysCacheGetAttr(STATEXTDATASTXOID, htup,
571  Anum_pg_statistic_ext_data_stxdmcv, &isnull);
572 
573  if (isnull)
574  elog(ERROR,
575  "requested statistics kind \"%c\" is not yet built for statistics object %u",
576  STATS_EXT_DEPENDENCIES, mvoid);
577 
578  result = statext_mcv_deserialize(DatumGetByteaP(mcvlist));
579 
580  ReleaseSysCache(htup);
581 
582  return result;
583 }
MCVList * statext_mcv_deserialize(bytea *data)
Definition: mcv.c:996
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
#define DatumGetByteaP(X)
Definition: fmgr.h:331
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
uintptr_t Datum
Definition: postgres.h:411
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1388
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define elog(elevel,...)
Definition: elog.h:232

◆ statext_ndistinct_load()

MVNDistinct* statext_ndistinct_load ( Oid  mvoid)

Definition at line 149 of file mvdistinct.c.

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

Referenced by estimate_multivariate_ndistinct().

150 {
151  MVNDistinct *result;
152  bool isnull;
153  Datum ndist;
154  HeapTuple htup;
155 
157  if (!HeapTupleIsValid(htup))
158  elog(ERROR, "cache lookup failed for statistics object %u", mvoid);
159 
160  ndist = SysCacheGetAttr(STATEXTDATASTXOID, htup,
161  Anum_pg_statistic_ext_data_stxdndistinct, &isnull);
162  if (isnull)
163  elog(ERROR,
164  "requested statistics kind \"%c\" is not yet built for statistics object %u",
165  STATS_EXT_NDISTINCT, mvoid);
166 
168 
169  ReleaseSysCache(htup);
170 
171  return result;
172 }
MVNDistinct * statext_ndistinct_deserialize(bytea *data)
Definition: mvdistinct.c:250
#define DatumGetByteaPP(X)
Definition: fmgr.h:291
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
uintptr_t Datum
Definition: postgres.h:411
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1388
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define elog(elevel,...)
Definition: elog.h:232