PostgreSQL Source Code git master
Data Structures | Macros | Typedefs | Functions
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 */
 
 

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)
 
 
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   MAX_STATISTICS_TARGET

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,
HeapTuplerows,
int  natts,
VacAttrStats **  vacattrstats 
)

Definition at line 111 of file extended_stats.c.

114{
115 Relation pg_stext;
116 ListCell *lc;
117 List *statslist;
118 MemoryContext cxt;
119 MemoryContext oldcxt;
120 int64 ext_cnt;
121
122 /* Do nothing if there are no columns to analyze. */
123 if (!natts)
124 return;
125
126 /* the list of stats has to be allocated outside the memory context */
127 pg_stext = table_open(StatisticExtRelationId, RowExclusiveLock);
128 statslist = fetch_statentries_for_relation(pg_stext, RelationGetRelid(onerel));
129
130 /* memory context for building each statistics object */
132 "BuildRelationExtStatistics",
134 oldcxt = MemoryContextSwitchTo(cxt);
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
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;
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(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),
179 errtable(onerel)));
180 continue;
181 }
182
183 /* compute statistics target for this statistics object */
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 object 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, exprdata, nexprs, rows, numrows);
223
224 exprstats = serialize_expr_stats(exprdata, nexprs);
225 }
226 }
227
228 /* store the statistics in the catalog */
229 statext_store(stat->statOid, inh,
230 ndistinct, dependencies, mcv, exprstats, stats);
231
232 /* for reporting progress */
234 ++ext_cnt);
235
236 /* free the data used for building this statistics object */
238 }
239
240 MemoryContextSwitchTo(oldcxt);
242
243 list_free(statslist);
244
245 table_close(pg_stext, RowExclusiveLock);
246}
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:751
int64_t int64
Definition: c.h:535
MVDependencies * statext_dependencies_build(StatsBuildData *data)
Definition: dependencies.c:348
int errcode(int sqlerrcode)
Definition: elog.c:854
int errmsg(const char *fmt,...)
Definition: elog.c:1071
#define WARNING
Definition: elog.h:36
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:226
#define ereport(elevel,...)
Definition: elog.h:150
static AnlExprData * build_expr_data(List *exprs, int stattarget)
static VacAttrStats ** lookup_var_attr_stats(Bitmapset *attrs, List *exprs, int nvacatts, VacAttrStats **vacatts)
static StatsBuildData * make_build_data(Relation rel, StatExtEntry *stat, int numrows, HeapTuple *rows, VacAttrStats **stats, int stattarget)
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 int statext_compute_stattarget(int stattarget, int nattrs, VacAttrStats **stats)
static void compute_expr_stats(Relation onerel, AnlExprData *exprdata, int nexprs, HeapTuple *rows, int numrows)
static Datum serialize_expr_stats(AnlExprData *exprdata, int nexprs)
long val
Definition: informix.c:689
void list_free(List *list)
Definition: list.c:1546
#define RowExclusiveLock
Definition: lockdefs.h:38
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3533
MCVList * statext_mcv_build(StatsBuildData *data, double totalrows, int stattarget)
Definition: mcv.c:180
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:400
MemoryContext CurrentMemoryContext
Definition: mcxt.c:160
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:469
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:160
#define AmAutoVacuumWorkerProcess()
Definition: miscadmin.h:382
MVNDistinct * statext_ndistinct_build(double totalrows, StatsBuildData *data)
Definition: mvdistinct.c:88
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
const void * data
#define lfirst(lc)
Definition: pg_list.h:172
static int list_length(const List *l)
Definition: pg_list.h:152
#define NIL
Definition: pg_list.h:68
#define lfirst_int(lc)
Definition: pg_list.h:173
uint64_t Datum
Definition: postgres.h:70
#define PROGRESS_ANALYZE_EXT_STATS_COMPUTED
Definition: progress.h:46
#define PROGRESS_ANALYZE_PHASE
Definition: progress.h:42
#define PROGRESS_ANALYZE_PHASE_COMPUTE_EXT_STATS
Definition: progress.h:56
#define PROGRESS_ANALYZE_EXT_STATS_TOTAL
Definition: progress.h:45
#define RelationGetRelid(relation)
Definition: rel.h:514
#define RelationGetRelationName(relation)
Definition: rel.h:548
int errtable(Relation rel)
Definition: relcache.c:6049
Definition: pg_list.h:54
Definition: rel.h:56
Form_pg_class rd_rel
Definition: rel.h:111
Definition: type.h:96
Definition: win32_port.h:255
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:40
Definition: pg_list.h:46

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, AmAutoVacuumWorkerProcess, bms_num_members(), build_expr_data(), compute_expr_stats(), CurrentMemoryContext, data, elog, ereport, errcode(), errmsg(), ERROR, errtable(), fetch_statentries_for_relation(), get_namespace_name(), 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 ( Liststats,
char  requiredkind,
bool  inh,
Bitmapset **  clause_attnums,
List **  clause_exprs,
int  nclauses 
)

Definition at line 1207 of file extended_stats.c.

1210{
1211 ListCell *lc;
1212 StatisticExtInfo *best_match = NULL;
1213 int best_num_matched = 2; /* goal #1: maximize */
1214 int best_match_keys = (STATS_MAX_DIMENSIONS + 1); /* goal #2: minimize */
1215
1216 foreach(lc, stats)
1217 {
1218 int i;
1220 Bitmapset *matched_attnums = NULL;
1221 Bitmapset *matched_exprs = NULL;
1222 int num_matched;
1223 int numkeys;
1224
1225 /* skip statistics that are not of the correct type */
1226 if (info->kind != requiredkind)
1227 continue;
1228
1229 /* skip statistics with mismatching inheritance flag */
1230 if (info->inherit != inh)
1231 continue;
1232
1233 /*
1234 * Collect attributes and expressions in remaining (unestimated)
1235 * clauses fully covered by this statistic object.
1236 *
1237 * We know already estimated clauses have both clause_attnums and
1238 * clause_exprs set to NULL. We leave the pointers NULL if already
1239 * estimated, or we reset them to NULL after estimating the clause.
1240 */
1241 for (i = 0; i < nclauses; i++)
1242 {
1243 Bitmapset *expr_idxs = NULL;
1244
1245 /* ignore incompatible/estimated clauses */
1246 if (!clause_attnums[i] && !clause_exprs[i])
1247 continue;
1248
1249 /* ignore clauses that are not covered by this object */
1250 if (!bms_is_subset(clause_attnums[i], info->keys) ||
1251 !stat_covers_expressions(info, clause_exprs[i], &expr_idxs))
1252 continue;
1253
1254 /* record attnums and indexes of expressions covered */
1255 matched_attnums = bms_add_members(matched_attnums, clause_attnums[i]);
1256 matched_exprs = bms_add_members(matched_exprs, expr_idxs);
1257 }
1258
1259 num_matched = bms_num_members(matched_attnums) + bms_num_members(matched_exprs);
1260
1261 bms_free(matched_attnums);
1262 bms_free(matched_exprs);
1263
1264 /*
1265 * save the actual number of keys in the stats so that we can choose
1266 * the narrowest stats with the most matching keys.
1267 */
1268 numkeys = bms_num_members(info->keys) + list_length(info->exprs);
1269
1270 /*
1271 * Use this object when it increases the number of matched attributes
1272 * and expressions or when it matches the same number of attributes
1273 * and expressions but these stats have fewer keys than any previous
1274 * match.
1275 */
1276 if (num_matched > best_num_matched ||
1277 (num_matched == best_num_matched && numkeys < best_match_keys))
1278 {
1279 best_match = info;
1280 best_num_matched = num_matched;
1281 best_match_keys = numkeys;
1282 }
1283 }
1284
1285 return best_match;
1286}
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:412
void bms_free(Bitmapset *a)
Definition: bitmapset.c:239
Bitmapset * bms_add_members(Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:917
static bool stat_covers_expressions(StatisticExtInfo *stat, List *exprs, Bitmapset **expr_idxs)
i
int i
Definition: isn.c:77
#define STATS_MAX_DIMENSIONS
Definition: statistics.h:19
List * exprs
Definition: pathnodes.h:1345
Bitmapset * keys
Definition: pathnodes.h:1342

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

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

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 ( PlannerInforoot,
Listclauses,
int  varRelid,
JoinType  jointype,
SpecialJoinInfosjinfo,
RelOptInforel,
Bitmapset **  estimatedclauses 
)

Definition at line 1370 of file dependencies.c.

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

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, root, s1, skip, statext_dependencies_load(), and RelOptInfo::statlist.

Referenced by statext_clauselist_selectivity().

has_stats_of_kind()

bool has_stats_of_kind ( Liststats,
char  requiredkind 
)

Definition at line 1116 of file extended_stats.c.

1117{
1118 ListCell *l;
1119
1120 foreach(l, stats)
1121 {
1123
1124 if (stat->kind == requiredkind)
1125 return true;
1126 }
1127
1128 return false;
1129}

References lfirst.

Referenced by dependencies_clauselist_selectivity(), and statext_mcv_clauselist_selectivity().

statext_clauselist_selectivity()

Selectivity statext_clauselist_selectivity ( PlannerInforoot,
Listclauses,
int  varRelid,
JoinType  jointype,
SpecialJoinInfosjinfo,
RelOptInforel,
Bitmapset **  estimatedclauses,
bool  is_or 
)

Definition at line 1982 of file extended_stats.c.

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

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

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

Referenced by dependencies_clauselist_selectivity().

statext_expressions_load()

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

Definition at line 2402 of file extended_stats.c.

2403{
2404 bool isnull;
2405 Datum value;
2406 HeapTuple htup;
2408 HeapTupleHeader td;
2409 HeapTupleData tmptup;
2410 HeapTuple tup;
2411
2412 htup = SearchSysCache2(STATEXTDATASTXOID,
2413 ObjectIdGetDatum(stxoid), BoolGetDatum(inh));
2414 if (!HeapTupleIsValid(htup))
2415 elog(ERROR, "cache lookup failed for statistics object %u", stxoid);
2416
2417 value = SysCacheGetAttr(STATEXTDATASTXOID, htup,
2418 Anum_pg_statistic_ext_data_stxdexpr, &isnull);
2419 if (isnull)
2420 elog(ERROR,
2421 "requested statistics kind \"%c\" is not yet built for statistics object %u",
2422 STATS_EXT_EXPRESSIONS, stxoid);
2423
2425
2427
2429
2430 /* Build a temporary HeapTuple control structure */
2432 ItemPointerSetInvalid(&(tmptup.t_self));
2433 tmptup.t_tableOid = InvalidOid;
2434 tmptup.t_data = td;
2435
2436 tup = heap_copytuple(&tmptup);
2437
2438 ReleaseSysCache(htup);
2439
2440 return tup;
2441}
void deconstruct_expanded_array(ExpandedArrayHeader *eah)
ExpandedArrayHeader * DatumGetExpandedArray(Datum d)
#define DatumGetHeapTupleHeader(X)
Definition: fmgr.h:295
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:778
static uint32 HeapTupleHeaderGetDatumLength(const HeapTupleHeaderData *tup)
Definition: htup_details.h:492
static struct @169 value
static void ItemPointerSetInvalid(ItemPointerData *pointer)
Definition: itemptr.h:184
#define InvalidOid
Definition: postgres_ext.h:37
Datum * dvalues
Definition: array.h:146
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(), 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 386 of file extended_stats.c.

387{
389
390 switch (type)
391 {
392 case STATS_EXT_NDISTINCT:
393 attnum = Anum_pg_statistic_ext_data_stxdndistinct;
394 break;
395
396 case STATS_EXT_DEPENDENCIES:
397 attnum = Anum_pg_statistic_ext_data_stxddependencies;
398 break;
399
400 case STATS_EXT_MCV:
401 attnum = Anum_pg_statistic_ext_data_stxdmcv;
402 break;
403
404 case STATS_EXT_EXPRESSIONS:
405 attnum = Anum_pg_statistic_ext_data_stxdexpr;
406 break;
407
408 default:
409 elog(ERROR, "unexpected statistics type requested: %d", type);
410 }
411
412 return !heap_attisnull(htup, attnum, NULL);
413}
bool heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc)
Definition: heaptuple.c:456
const char * type

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

Referenced by get_relation_statistics_worker().

statext_mcv_load()

MCVList * statext_mcv_load ( Oid  mvoid,
bool  inh 
)

Definition at line 558 of file mcv.c.

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

References BoolGetDatum(), DatumGetByteaP, elog, ERROR, HeapTupleIsValid, ObjectIdGetDatum(), ReleaseSysCache(), SearchSysCache2(), statext_mcv_deserialize(), 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 148 of file mvdistinct.c.

149{
150 MVNDistinct *result;
151 bool isnull;
152 Datum ndist;
153 HeapTuple htup;
154
155 htup = SearchSysCache2(STATEXTDATASTXOID,
156 ObjectIdGetDatum(mvoid), BoolGetDatum(inh));
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

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

Referenced by estimate_multivariate_ndistinct().

AltStyle によって変換されたページ (->オリジナル) /