PostgreSQL Source Code  git master
attribute_stats.c File Reference
#include "postgres.h"
#include "access/heapam.h"
#include "catalog/indexing.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_operator.h"
#include "nodes/nodeFuncs.h"
#include "statistics/statistics.h"
#include "statistics/stat_utils.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/lsyscache.h"
#include "utils/syscache.h"
Include dependency graph for attribute_stats.c:

Go to the source code of this file.

Macros

#define DEFAULT_NULL_FRAC   Float4GetDatum(0.0)
 
#define DEFAULT_AVG_WIDTH   Int32GetDatum(0) /* unknown */
 
#define DEFAULT_N_DISTINCT   Float4GetDatum(0.0) /* unknown */
 

Enumerations

enum  attribute_stats_argnum {
  ATTRELATION_ARG = 0 , ATTNAME_ARG , INHERITED_ARG , NULL_FRAC_ARG ,
  AVG_WIDTH_ARG , N_DISTINCT_ARG , MOST_COMMON_VALS_ARG , MOST_COMMON_FREQS_ARG ,
  HISTOGRAM_BOUNDS_ARG , CORRELATION_ARG , MOST_COMMON_ELEMS_ARG , MOST_COMMON_ELEM_FREQS_ARG ,
  ELEM_COUNT_HISTOGRAM_ARG , RANGE_LENGTH_HISTOGRAM_ARG , RANGE_EMPTY_FRAC_ARG , RANGE_BOUNDS_HISTOGRAM_ARG ,
  NUM_ATTRIBUTE_STATS_ARGS
}
 

Functions

static bool attribute_statistics_update (FunctionCallInfo fcinfo, int elevel)
 
static Nodeget_attr_expr (Relation rel, int attnum)
 
static void get_attr_stat_type (Oid reloid, AttrNumber attnum, int elevel, Oid *atttypid, int32 *atttypmod, char *atttyptype, Oid *atttypcoll, Oid *eq_opr, Oid *lt_opr)
 
static bool get_elem_stat_type (Oid atttypid, char atttyptype, int elevel, Oid *elemtypid, Oid *elem_eq_opr)
 
static Datum text_to_stavalues (const char *staname, FmgrInfo *array_in, Datum d, Oid typid, int32 typmod, int elevel, bool *ok)
 
static void set_stats_slot (Datum *values, bool *nulls, bool *replaces, int16 stakind, Oid staop, Oid stacoll, Datum stanumbers, bool stanumbers_isnull, Datum stavalues, bool stavalues_isnull)
 
static void upsert_pg_statistic (Relation starel, HeapTuple oldtup, Datum *values, bool *nulls, bool *replaces)
 
static bool delete_pg_statistic (Oid reloid, AttrNumber attnum, bool stainherit)
 
static void init_empty_stats_tuple (Oid reloid, int16 attnum, bool inherited, Datum *values, bool *nulls, bool *replaces)
 
Datum pg_set_attribute_stats (PG_FUNCTION_ARGS)
 
Datum pg_clear_attribute_stats (PG_FUNCTION_ARGS)
 

Variables

static struct StatsArgInfo attarginfo []
 

Macro Definition Documentation

◆ DEFAULT_AVG_WIDTH

#define DEFAULT_AVG_WIDTH   Int32GetDatum(0) /* unknown */

Definition at line 34 of file attribute_stats.c.

◆ DEFAULT_N_DISTINCT

#define DEFAULT_N_DISTINCT   Float4GetDatum(0.0) /* unknown */

Definition at line 35 of file attribute_stats.c.

◆ DEFAULT_NULL_FRAC

#define DEFAULT_NULL_FRAC   Float4GetDatum(0.0)

Definition at line 33 of file attribute_stats.c.

Enumeration Type Documentation

◆ attribute_stats_argnum

Enumerator
ATTRELATION_ARG 
ATTNAME_ARG 
INHERITED_ARG 
NULL_FRAC_ARG 
AVG_WIDTH_ARG 
N_DISTINCT_ARG 
MOST_COMMON_VALS_ARG 
MOST_COMMON_FREQS_ARG 
HISTOGRAM_BOUNDS_ARG 
CORRELATION_ARG 
MOST_COMMON_ELEMS_ARG 
MOST_COMMON_ELEM_FREQS_ARG 
ELEM_COUNT_HISTOGRAM_ARG 
RANGE_LENGTH_HISTOGRAM_ARG 
RANGE_EMPTY_FRAC_ARG 
RANGE_BOUNDS_HISTOGRAM_ARG 
NUM_ATTRIBUTE_STATS_ARGS 

Definition at line 37 of file attribute_stats.c.

38 {
39  ATTRELATION_ARG = 0,
56 };
@ RANGE_LENGTH_HISTOGRAM_ARG
@ RANGE_BOUNDS_HISTOGRAM_ARG
@ AVG_WIDTH_ARG
@ INHERITED_ARG
@ ATTRELATION_ARG
@ MOST_COMMON_ELEMS_ARG
@ NULL_FRAC_ARG
@ NUM_ATTRIBUTE_STATS_ARGS
@ MOST_COMMON_FREQS_ARG
@ CORRELATION_ARG
@ HISTOGRAM_BOUNDS_ARG
@ MOST_COMMON_VALS_ARG
@ RANGE_EMPTY_FRAC_ARG
@ ELEM_COUNT_HISTOGRAM_ARG
@ ATTNAME_ARG
@ N_DISTINCT_ARG
@ MOST_COMMON_ELEM_FREQS_ARG

Function Documentation

◆ attribute_statistics_update()

static bool attribute_statistics_update ( FunctionCallInfo  fcinfo,
int  elevel 
)
static

Definition at line 116 of file attribute_stats.c.

117 {
118  Oid reloid;
119  Name attname;
120  bool inherited;
122 
123  Relation starel;
124  HeapTuple statup;
125 
126  Oid atttypid = InvalidOid;
127  int32 atttypmod;
128  char atttyptype;
129  Oid atttypcoll = InvalidOid;
130  Oid eq_opr = InvalidOid;
131  Oid lt_opr = InvalidOid;
132 
133  Oid elemtypid = InvalidOid;
134  Oid elem_eq_opr = InvalidOid;
135 
136  FmgrInfo array_in_fn;
137 
138  bool do_mcv = !PG_ARGISNULL(MOST_COMMON_FREQS_ARG) &&
140  bool do_histogram = !PG_ARGISNULL(HISTOGRAM_BOUNDS_ARG);
141  bool do_correlation = !PG_ARGISNULL(CORRELATION_ARG);
142  bool do_mcelem = !PG_ARGISNULL(MOST_COMMON_ELEMS_ARG) &&
144  bool do_dechist = !PG_ARGISNULL(ELEM_COUNT_HISTOGRAM_ARG);
145  bool do_bounds_histogram = !PG_ARGISNULL(RANGE_BOUNDS_HISTOGRAM_ARG);
146  bool do_range_length_histogram = !PG_ARGISNULL(RANGE_LENGTH_HISTOGRAM_ARG) &&
148 
149  Datum values[Natts_pg_statistic] = {0};
150  bool nulls[Natts_pg_statistic] = {0};
151  bool replaces[Natts_pg_statistic] = {0};
152 
153  bool result = true;
154 
156  reloid = PG_GETARG_OID(ATTRELATION_ARG);
157 
158  /* lock before looking up attribute */
160 
163  attnum = get_attnum(reloid, NameStr(*attname));
164  if (attnum == InvalidAttrNumber)
165  ereport(ERROR,
166  (errcode(ERRCODE_UNDEFINED_COLUMN),
167  errmsg("column \"%s\" of relation \"%s\" does not exist",
168  NameStr(*attname), get_rel_name(reloid))));
169 
171  inherited = PG_GETARG_BOOL(INHERITED_ARG);
172 
173  /*
174  * Check argument sanity. If some arguments are unusable, emit at elevel
175  * and set the corresponding argument to NULL in fcinfo.
176  */
177 
179  elevel))
180  {
181  do_mcv = false;
182  result = false;
183  }
184 
186  elevel))
187  {
188  do_mcelem = false;
189  result = false;
190  }
192  elevel))
193  {
194  do_dechist = false;
195  result = false;
196  }
197 
198  if (!stats_check_arg_pair(fcinfo, attarginfo,
200  elevel))
201  {
202  do_mcv = false;
203  result = false;
204  }
205 
206  if (!stats_check_arg_pair(fcinfo, attarginfo,
209  {
210  do_mcelem = false;
211  result = false;
212  }
213 
214  if (!stats_check_arg_pair(fcinfo, attarginfo,
216  RANGE_EMPTY_FRAC_ARG, elevel))
217  {
218  do_range_length_histogram = false;
219  result = false;
220  }
221 
222  /* derive information from attribute */
223  get_attr_stat_type(reloid, attnum, elevel,
224  &atttypid, &atttypmod,
225  &atttyptype, &atttypcoll,
226  &eq_opr, &lt_opr);
227 
228  /* if needed, derive element type */
229  if (do_mcelem || do_dechist)
230  {
231  if (!get_elem_stat_type(atttypid, atttyptype, elevel,
232  &elemtypid, &elem_eq_opr))
233  {
234  ereport(elevel,
235  (errmsg("unable to determine element type of attribute \"%s\"", NameStr(*attname)),
236  errdetail("Cannot set STATISTIC_KIND_MCELEM or STATISTIC_KIND_DECHIST.")));
237  elemtypid = InvalidOid;
238  elem_eq_opr = InvalidOid;
239 
240  do_mcelem = false;
241  do_dechist = false;
242  result = false;
243  }
244  }
245 
246  /* histogram and correlation require less-than operator */
247  if ((do_histogram || do_correlation) && !OidIsValid(lt_opr))
248  {
249  ereport(elevel,
250  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
251  errmsg("could not determine less-than operator for attribute \"%s\"", NameStr(*attname)),
252  errdetail("Cannot set STATISTIC_KIND_HISTOGRAM or STATISTIC_KIND_CORRELATION.")));
253 
254  do_histogram = false;
255  do_correlation = false;
256  result = false;
257  }
258 
259  /* only range types can have range stats */
260  if ((do_range_length_histogram || do_bounds_histogram) &&
261  !(atttyptype == TYPTYPE_RANGE || atttyptype == TYPTYPE_MULTIRANGE))
262  {
263  ereport(elevel,
264  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
265  errmsg("attribute \"%s\" is not a range type", NameStr(*attname)),
266  errdetail("Cannot set STATISTIC_KIND_RANGE_LENGTH_HISTOGRAM or STATISTIC_KIND_BOUNDS_HISTOGRAM.")));
267 
268  do_bounds_histogram = false;
269  do_range_length_histogram = false;
270  result = false;
271  }
272 
273  fmgr_info(F_ARRAY_IN, &array_in_fn);
274 
275  starel = table_open(StatisticRelationId, RowExclusiveLock);
276 
277  statup = SearchSysCache3(STATRELATTINH, reloid, attnum, inherited);
278 
279  /* initialize from existing tuple if exists */
280  if (HeapTupleIsValid(statup))
281  heap_deform_tuple(statup, RelationGetDescr(starel), values, nulls);
282  else
283  init_empty_stats_tuple(reloid, attnum, inherited, values, nulls,
284  replaces);
285 
286  /* if specified, set to argument values */
288  {
289  values[Anum_pg_statistic_stanullfrac - 1] = PG_GETARG_DATUM(NULL_FRAC_ARG);
290  replaces[Anum_pg_statistic_stanullfrac - 1] = true;
291  }
293  {
294  values[Anum_pg_statistic_stawidth - 1] = PG_GETARG_DATUM(AVG_WIDTH_ARG);
295  replaces[Anum_pg_statistic_stawidth - 1] = true;
296  }
298  {
299  values[Anum_pg_statistic_stadistinct - 1] = PG_GETARG_DATUM(N_DISTINCT_ARG);
300  replaces[Anum_pg_statistic_stadistinct - 1] = true;
301  }
302 
303  /* STATISTIC_KIND_MCV */
304  if (do_mcv)
305  {
306  bool converted;
308  Datum stavalues = text_to_stavalues("most_common_vals",
309  &array_in_fn,
311  atttypid, atttypmod,
312  elevel, &converted);
313 
314  if (converted)
315  {
316  set_stats_slot(values, nulls, replaces,
317  STATISTIC_KIND_MCV,
318  eq_opr, atttypcoll,
319  stanumbers, false, stavalues, false);
320  }
321  else
322  result = false;
323  }
324 
325  /* STATISTIC_KIND_HISTOGRAM */
326  if (do_histogram)
327  {
328  Datum stavalues;
329  bool converted = false;
330 
331  stavalues = text_to_stavalues("histogram_bounds",
332  &array_in_fn,
334  atttypid, atttypmod, elevel,
335  &converted);
336 
337  if (converted)
338  {
339  set_stats_slot(values, nulls, replaces,
340  STATISTIC_KIND_HISTOGRAM,
341  lt_opr, atttypcoll,
342  0, true, stavalues, false);
343  }
344  else
345  result = false;
346  }
347 
348  /* STATISTIC_KIND_CORRELATION */
349  if (do_correlation)
350  {
352  ArrayType *arry = construct_array_builtin(elems, 1, FLOAT4OID);
353  Datum stanumbers = PointerGetDatum(arry);
354 
355  set_stats_slot(values, nulls, replaces,
356  STATISTIC_KIND_CORRELATION,
357  lt_opr, atttypcoll,
358  stanumbers, false, 0, true);
359  }
360 
361  /* STATISTIC_KIND_MCELEM */
362  if (do_mcelem)
363  {
365  bool converted = false;
366  Datum stavalues;
367 
368  stavalues = text_to_stavalues("most_common_elems",
369  &array_in_fn,
371  elemtypid, atttypmod,
372  elevel, &converted);
373 
374  if (converted)
375  {
376  set_stats_slot(values, nulls, replaces,
377  STATISTIC_KIND_MCELEM,
378  elem_eq_opr, atttypcoll,
379  stanumbers, false, stavalues, false);
380  }
381  else
382  result = false;
383  }
384 
385  /* STATISTIC_KIND_DECHIST */
386  if (do_dechist)
387  {
389 
390  set_stats_slot(values, nulls, replaces,
391  STATISTIC_KIND_DECHIST,
392  elem_eq_opr, atttypcoll,
393  stanumbers, false, 0, true);
394  }
395 
396  /*
397  * STATISTIC_KIND_BOUNDS_HISTOGRAM
398  *
399  * This stakind appears before STATISTIC_KIND_RANGE_LENGTH_HISTOGRAM even
400  * though it is numerically greater, and all other stakinds appear in
401  * numerical order. We duplicate this quirk for consistency.
402  */
403  if (do_bounds_histogram)
404  {
405  bool converted = false;
406  Datum stavalues;
407 
408  stavalues = text_to_stavalues("range_bounds_histogram",
409  &array_in_fn,
411  atttypid, atttypmod,
412  elevel, &converted);
413 
414  if (converted)
415  {
416  set_stats_slot(values, nulls, replaces,
417  STATISTIC_KIND_BOUNDS_HISTOGRAM,
419  0, true, stavalues, false);
420  }
421  else
422  result = false;
423  }
424 
425  /* STATISTIC_KIND_RANGE_LENGTH_HISTOGRAM */
426  if (do_range_length_histogram)
427  {
428  /* The anyarray is always a float8[] for this stakind */
430  ArrayType *arry = construct_array_builtin(elems, 1, FLOAT4OID);
431  Datum stanumbers = PointerGetDatum(arry);
432 
433  bool converted = false;
434  Datum stavalues;
435 
436  stavalues = text_to_stavalues("range_length_histogram",
437  &array_in_fn,
439  FLOAT8OID, 0, elevel, &converted);
440 
441  if (converted)
442  {
443  set_stats_slot(values, nulls, replaces,
444  STATISTIC_KIND_RANGE_LENGTH_HISTOGRAM,
445  Float8LessOperator, InvalidOid,
446  stanumbers, false, stavalues, false);
447  }
448  else
449  result = false;
450  }
451 
452  upsert_pg_statistic(starel, statup, values, nulls, replaces);
453 
454  if (HeapTupleIsValid(statup))
455  ReleaseSysCache(statup);
456  table_close(starel, RowExclusiveLock);
457 
458  return result;
459 }
ArrayType * construct_array_builtin(Datum *elems, int nelems, Oid elmtype)
Definition: arrayfuncs.c:3381
int16 AttrNumber
Definition: attnum.h:21
#define InvalidAttrNumber
Definition: attnum.h:23
static Datum text_to_stavalues(const char *staname, FmgrInfo *array_in, Datum d, Oid typid, int32 typmod, int elevel, bool *ok)
static bool get_elem_stat_type(Oid atttypid, char atttyptype, int elevel, Oid *elemtypid, Oid *elem_eq_opr)
static struct StatsArgInfo attarginfo[]
static void get_attr_stat_type(Oid reloid, AttrNumber attnum, int elevel, Oid *atttypid, int32 *atttypmod, char *atttyptype, Oid *atttypcoll, Oid *eq_opr, Oid *lt_opr)
static void init_empty_stats_tuple(Oid reloid, int16 attnum, bool inherited, Datum *values, bool *nulls, bool *replaces)
static void set_stats_slot(Datum *values, bool *nulls, bool *replaces, int16 stakind, Oid staop, Oid stacoll, Datum stanumbers, bool stanumbers_isnull, Datum stavalues, bool stavalues_isnull)
static void upsert_pg_statistic(Relation starel, HeapTuple oldtup, Datum *values, bool *nulls, bool *replaces)
static Datum values[MAXATTR]
Definition: bootstrap.c:150
#define NameStr(name)
Definition: c.h:737
signed int int32
Definition: c.h:496
#define OidIsValid(objectId)
Definition: c.h:766
int errdetail(const char *fmt,...)
Definition: elog.c:1203
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:127
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
#define PG_ARGISNULL(n)
Definition: fmgr.h:209
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:268
#define PG_GETARG_NAME(n)
Definition: fmgr.h:278
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:274
void heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *values, bool *isnull)
Definition: heaptuple.c:1345
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define RowExclusiveLock
Definition: lockdefs.h:38
AttrNumber get_attnum(Oid relid, const char *attname)
Definition: lsyscache.c:858
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1928
NameData attname
Definition: pg_attribute.h:41
int16 attnum
Definition: pg_attribute.h:74
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:322
uintptr_t Datum
Definition: postgres.h:64
#define InvalidOid
Definition: postgres_ext.h:36
unsigned int Oid
Definition: postgres_ext.h:31
#define RelationGetDescr(relation)
Definition: rel.h:531
bool stats_check_arg_array(FunctionCallInfo fcinfo, struct StatsArgInfo *arginfo, int argnum, int elevel)
Definition: stat_utils.c:51
void stats_check_required_arg(FunctionCallInfo fcinfo, struct StatsArgInfo *arginfo, int argnum)
Definition: stat_utils.c:32
bool stats_check_arg_pair(FunctionCallInfo fcinfo, struct StatsArgInfo *arginfo, int argnum1, int argnum2, int elevel)
Definition: stat_utils.c:92
void stats_lock_check_privileges(Oid reloid)
Definition: stat_utils.c:126
Definition: fmgr.h:57
Definition: c.h:732
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:269
HeapTuple SearchSysCache3(int cacheId, Datum key1, Datum key2, Datum key3)
Definition: syscache.c:243
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:40

References attarginfo, attname, ATTNAME_ARG, attnum, ATTRELATION_ARG, AVG_WIDTH_ARG, construct_array_builtin(), CORRELATION_ARG, ELEM_COUNT_HISTOGRAM_ARG, ereport, errcode(), errdetail(), errmsg(), ERROR, fmgr_info(), get_attnum(), get_attr_stat_type(), get_elem_stat_type(), get_rel_name(), heap_deform_tuple(), HeapTupleIsValid, HISTOGRAM_BOUNDS_ARG, INHERITED_ARG, init_empty_stats_tuple(), InvalidAttrNumber, InvalidOid, MOST_COMMON_ELEM_FREQS_ARG, MOST_COMMON_ELEMS_ARG, MOST_COMMON_FREQS_ARG, MOST_COMMON_VALS_ARG, N_DISTINCT_ARG, NameStr, NULL_FRAC_ARG, OidIsValid, PG_ARGISNULL, PG_GETARG_BOOL, PG_GETARG_DATUM, PG_GETARG_NAME, PG_GETARG_OID, PointerGetDatum(), RANGE_BOUNDS_HISTOGRAM_ARG, RANGE_EMPTY_FRAC_ARG, RANGE_LENGTH_HISTOGRAM_ARG, RelationGetDescr, ReleaseSysCache(), RowExclusiveLock, SearchSysCache3(), set_stats_slot(), stats_check_arg_array(), stats_check_arg_pair(), stats_check_required_arg(), stats_lock_check_privileges(), table_close(), table_open(), text_to_stavalues(), upsert_pg_statistic(), and values.

Referenced by pg_set_attribute_stats().

◆ delete_pg_statistic()

static bool delete_pg_statistic ( Oid  reloid,
AttrNumber  attnum,
bool  stainherit 
)
static

Definition at line 761 of file attribute_stats.c.

762 {
763  Relation sd = table_open(StatisticRelationId, RowExclusiveLock);
764  HeapTuple oldtup;
765 
766  /* Is there already a pg_statistic tuple for this attribute? */
767  oldtup = SearchSysCache3(STATRELATTINH,
768  ObjectIdGetDatum(reloid),
770  BoolGetDatum(stainherit));
771 
772  if (HeapTupleIsValid(oldtup))
773  {
774  CatalogTupleDelete(sd, &oldtup->t_self);
775  ReleaseSysCache(oldtup);
777  return true;
778  }
779 
781  return false;
782 }
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:365
static Datum Int16GetDatum(int16 X)
Definition: postgres.h:172
static Datum BoolGetDatum(bool X)
Definition: postgres.h:102
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
ItemPointerData t_self
Definition: htup.h:65

References attnum, BoolGetDatum(), CatalogTupleDelete(), HeapTupleIsValid, Int16GetDatum(), ObjectIdGetDatum(), ReleaseSysCache(), RowExclusiveLock, SearchSysCache3(), HeapTupleData::t_self, table_close(), and table_open().

Referenced by pg_clear_attribute_stats().

◆ get_attr_expr()

static Node * get_attr_expr ( Relation  rel,
int  attnum 
)
static

Definition at line 468 of file attribute_stats.c.

469 {
470  if ((rel->rd_rel->relkind == RELKIND_INDEX
471  || (rel->rd_rel->relkind == RELKIND_PARTITIONED_INDEX))
472  && (rel->rd_indexprs != NIL)
473  && (rel->rd_index->indkey.values[attnum - 1] == 0))
474  {
475  ListCell *indexpr_item = list_head(rel->rd_indexprs);
476 
477  for (int i = 0; i < attnum - 1; i++)
478  if (rel->rd_index->indkey.values[i] == 0)
479  indexpr_item = lnext(rel->rd_indexprs, indexpr_item);
480 
481  if (indexpr_item == NULL) /* shouldn't happen */
482  elog(ERROR, "too few entries in indexprs list");
483 
484  return (Node *) lfirst(indexpr_item);
485  }
486  return NULL;
487 }
#define elog(elevel,...)
Definition: elog.h:225
int i
Definition: isn.c:73
#define lfirst(lc)
Definition: pg_list.h:172
#define NIL
Definition: pg_list.h:68
static ListCell * list_head(const List *l)
Definition: pg_list.h:128
static ListCell * lnext(const List *l, const ListCell *c)
Definition: pg_list.h:343
Definition: nodes.h:129
List * rd_indexprs
Definition: rel.h:212
Form_pg_index rd_index
Definition: rel.h:192
Form_pg_class rd_rel
Definition: rel.h:111

References attnum, elog, ERROR, i, lfirst, list_head(), lnext(), NIL, RelationData::rd_index, RelationData::rd_indexprs, and RelationData::rd_rel.

Referenced by get_attr_stat_type().

◆ get_attr_stat_type()

static void get_attr_stat_type ( Oid  reloid,
AttrNumber  attnum,
int  elevel,
Oid atttypid,
int32 atttypmod,
char *  atttyptype,
Oid atttypcoll,
Oid eq_opr,
Oid lt_opr 
)
static

Definition at line 493 of file attribute_stats.c.

497 {
498  Relation rel = relation_open(reloid, AccessShareLock);
499  Form_pg_attribute attr;
500  HeapTuple atup;
501  Node *expr;
502  TypeCacheEntry *typcache;
503 
504  atup = SearchSysCache2(ATTNUM, ObjectIdGetDatum(reloid),
506 
507  /* Attribute not found */
508  if (!HeapTupleIsValid(atup))
509  ereport(ERROR,
510  (errcode(ERRCODE_UNDEFINED_COLUMN),
511  errmsg("attribute %d of relation \"%s\" does not exist",
513 
514  attr = (Form_pg_attribute) GETSTRUCT(atup);
515 
516  if (attr->attisdropped)
517  ereport(ERROR,
518  (errcode(ERRCODE_UNDEFINED_COLUMN),
519  errmsg("attribute %d of relation \"%s\" does not exist",
521 
522  expr = get_attr_expr(rel, attr->attnum);
523 
524  /*
525  * When analyzing an expression index, believe the expression tree's type
526  * not the column datatype --- the latter might be the opckeytype storage
527  * type of the opclass, which is not interesting for our purposes. This
528  * mimics the behvior of examine_attribute().
529  */
530  if (expr == NULL)
531  {
532  *atttypid = attr->atttypid;
533  *atttypmod = attr->atttypmod;
534  *atttypcoll = attr->attcollation;
535  }
536  else
537  {
538  *atttypid = exprType(expr);
539  *atttypmod = exprTypmod(expr);
540 
541  if (OidIsValid(attr->attcollation))
542  *atttypcoll = attr->attcollation;
543  else
544  *atttypcoll = exprCollation(expr);
545  }
546  ReleaseSysCache(atup);
547 
548  /*
549  * If it's a multirange, step down to the range type, as is done by
550  * multirange_typanalyze().
551  */
552  if (type_is_multirange(*atttypid))
553  *atttypid = get_multirange_range(*atttypid);
554 
555  /* finds the right operators even if atttypid is a domain */
556  typcache = lookup_type_cache(*atttypid, TYPECACHE_LT_OPR | TYPECACHE_EQ_OPR);
557  *atttyptype = typcache->typtype;
558  *eq_opr = typcache->eq_opr;
559  *lt_opr = typcache->lt_opr;
560 
561  /*
562  * Special case: collation for tsvector is DEFAULT_COLLATION_OID. See
563  * compute_tsvector_stats().
564  */
565  if (*atttypid == TSVECTOROID)
566  *atttypcoll = DEFAULT_COLLATION_OID;
567 
568  relation_close(rel, NoLock);
569 }
static Node * get_attr_expr(Relation rel, int attnum)
#define GETSTRUCT(TUP)
Definition: htup_details.h:653
#define NoLock
Definition: lockdefs.h:34
#define AccessShareLock
Definition: lockdefs.h:36
Oid get_multirange_range(Oid multirangeOid)
Definition: lsyscache.c:3483
bool type_is_multirange(Oid typid)
Definition: lsyscache.c:2698
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
int32 exprTypmod(const Node *expr)
Definition: nodeFuncs.c:298
Oid exprCollation(const Node *expr)
Definition: nodeFuncs.c:816
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:209
#define RelationGetRelationName(relation)
Definition: rel.h:539
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: relation.c:205
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: relation.c:47
char typtype
Definition: typcache.h:43
HeapTuple SearchSysCache2(int cacheId, Datum key1, Datum key2)
Definition: syscache.c:232
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:356
#define TYPECACHE_EQ_OPR
Definition: typcache.h:137
#define TYPECACHE_LT_OPR
Definition: typcache.h:138

References AccessShareLock, attnum, TypeCacheEntry::eq_opr, ereport, errcode(), errmsg(), ERROR, exprCollation(), exprType(), exprTypmod(), get_attr_expr(), get_multirange_range(), GETSTRUCT, HeapTupleIsValid, Int16GetDatum(), lookup_type_cache(), TypeCacheEntry::lt_opr, NoLock, ObjectIdGetDatum(), OidIsValid, relation_close(), relation_open(), RelationGetRelationName, ReleaseSysCache(), SearchSysCache2(), type_is_multirange(), TYPECACHE_EQ_OPR, TYPECACHE_LT_OPR, and TypeCacheEntry::typtype.

Referenced by attribute_statistics_update().

◆ get_elem_stat_type()

static bool get_elem_stat_type ( Oid  atttypid,
char  atttyptype,
int  elevel,
Oid elemtypid,
Oid elem_eq_opr 
)
static

Definition at line 575 of file attribute_stats.c.

577 {
578  TypeCacheEntry *elemtypcache;
579 
580  if (atttypid == TSVECTOROID)
581  {
582  /*
583  * Special case: element type for tsvector is text. See
584  * compute_tsvector_stats().
585  */
586  *elemtypid = TEXTOID;
587  }
588  else
589  {
590  /* find underlying element type through any domain */
591  *elemtypid = get_base_element_type(atttypid);
592  }
593 
594  if (!OidIsValid(*elemtypid))
595  return false;
596 
597  /* finds the right operator even if elemtypid is a domain */
598  elemtypcache = lookup_type_cache(*elemtypid, TYPECACHE_EQ_OPR);
599  if (!OidIsValid(elemtypcache->eq_opr))
600  return false;
601 
602  *elem_eq_opr = elemtypcache->eq_opr;
603 
604  return true;
605 }
Oid get_base_element_type(Oid typid)
Definition: lsyscache.c:2832

References TypeCacheEntry::eq_opr, get_base_element_type(), lookup_type_cache(), OidIsValid, and TYPECACHE_EQ_OPR.

Referenced by attribute_statistics_update().

◆ init_empty_stats_tuple()

static void init_empty_stats_tuple ( Oid  reloid,
int16  attnum,
bool  inherited,
Datum values,
bool nulls,
bool replaces 
)
static

Definition at line 788 of file attribute_stats.c.

790 {
791  memset(nulls, true, sizeof(bool) * Natts_pg_statistic);
792  memset(replaces, true, sizeof(bool) * Natts_pg_statistic);
793 
794  /* must initialize non-NULL attributes */
795 
796  values[Anum_pg_statistic_starelid - 1] = ObjectIdGetDatum(reloid);
797  nulls[Anum_pg_statistic_starelid - 1] = false;
798  values[Anum_pg_statistic_staattnum - 1] = Int16GetDatum(attnum);
799  nulls[Anum_pg_statistic_staattnum - 1] = false;
800  values[Anum_pg_statistic_stainherit - 1] = BoolGetDatum(inherited);
801  nulls[Anum_pg_statistic_stainherit - 1] = false;
802 
803  values[Anum_pg_statistic_stanullfrac - 1] = DEFAULT_NULL_FRAC;
804  nulls[Anum_pg_statistic_stanullfrac - 1] = false;
805  values[Anum_pg_statistic_stawidth - 1] = DEFAULT_AVG_WIDTH;
806  nulls[Anum_pg_statistic_stawidth - 1] = false;
807  values[Anum_pg_statistic_stadistinct - 1] = DEFAULT_N_DISTINCT;
808  nulls[Anum_pg_statistic_stadistinct - 1] = false;
809 
810  /* initialize stakind, staop, and stacoll slots */
811  for (int slotnum = 0; slotnum < STATISTIC_NUM_SLOTS; slotnum++)
812  {
813  values[Anum_pg_statistic_stakind1 + slotnum - 1] = (Datum) 0;
814  nulls[Anum_pg_statistic_stakind1 + slotnum - 1] = false;
815  values[Anum_pg_statistic_staop1 + slotnum - 1] = InvalidOid;
816  nulls[Anum_pg_statistic_staop1 + slotnum - 1] = false;
817  values[Anum_pg_statistic_stacoll1 + slotnum - 1] = InvalidOid;
818  nulls[Anum_pg_statistic_stacoll1 + slotnum - 1] = false;
819  }
820 }
#define DEFAULT_NULL_FRAC
#define DEFAULT_N_DISTINCT
#define DEFAULT_AVG_WIDTH
#define STATISTIC_NUM_SLOTS
Definition: pg_statistic.h:127

References attnum, BoolGetDatum(), DEFAULT_AVG_WIDTH, DEFAULT_N_DISTINCT, DEFAULT_NULL_FRAC, Int16GetDatum(), InvalidOid, ObjectIdGetDatum(), STATISTIC_NUM_SLOTS, and values.

Referenced by attribute_statistics_update().

◆ pg_clear_attribute_stats()

Datum pg_clear_attribute_stats ( PG_FUNCTION_ARGS  )

Definition at line 853 of file attribute_stats.c.

854 {
855  Oid reloid;
856  Name attname;
858  bool inherited;
859 
861  reloid = PG_GETARG_OID(ATTRELATION_ARG);
862 
864 
867  attnum = get_attnum(reloid, NameStr(*attname));
868  if (attnum == InvalidAttrNumber)
869  ereport(ERROR,
870  (errcode(ERRCODE_UNDEFINED_COLUMN),
871  errmsg("column \"%s\" of relation \"%s\" does not exist",
872  NameStr(*attname), get_rel_name(reloid))));
873 
875  inherited = PG_GETARG_BOOL(INHERITED_ARG);
876 
877  delete_pg_statistic(reloid, attnum, inherited);
878  PG_RETURN_VOID();
879 }
static bool delete_pg_statistic(Oid reloid, AttrNumber attnum, bool stainherit)
#define PG_RETURN_VOID()
Definition: fmgr.h:349

References attarginfo, attname, ATTNAME_ARG, attnum, ATTRELATION_ARG, delete_pg_statistic(), ereport, errcode(), errmsg(), ERROR, get_attnum(), get_rel_name(), INHERITED_ARG, InvalidAttrNumber, NameStr, PG_GETARG_BOOL, PG_GETARG_NAME, PG_GETARG_OID, PG_RETURN_VOID, stats_check_required_arg(), and stats_lock_check_privileges().

◆ pg_set_attribute_stats()

Datum pg_set_attribute_stats ( PG_FUNCTION_ARGS  )

Definition at line 843 of file attribute_stats.c.

844 {
846  PG_RETURN_VOID();
847 }
static bool attribute_statistics_update(FunctionCallInfo fcinfo, int elevel)

References attribute_statistics_update(), ERROR, and PG_RETURN_VOID.

◆ set_stats_slot()

static void set_stats_slot ( Datum values,
bool nulls,
bool replaces,
int16  stakind,
Oid  staop,
Oid  stacoll,
Datum  stanumbers,
bool  stanumbers_isnull,
Datum  stavalues,
bool  stavalues_isnull 
)
static

Definition at line 669 of file attribute_stats.c.

673 {
674  int slotidx;
675  int first_empty = -1;
676  AttrNumber stakind_attnum;
677  AttrNumber staop_attnum;
678  AttrNumber stacoll_attnum;
679 
680  /* find existing slot with given stakind */
681  for (slotidx = 0; slotidx < STATISTIC_NUM_SLOTS; slotidx++)
682  {
683  stakind_attnum = Anum_pg_statistic_stakind1 - 1 + slotidx;
684 
685  if (first_empty < 0 &&
686  DatumGetInt16(values[stakind_attnum]) == 0)
687  first_empty = slotidx;
688  if (DatumGetInt16(values[stakind_attnum]) == stakind)
689  break;
690  }
691 
692  if (slotidx >= STATISTIC_NUM_SLOTS && first_empty >= 0)
693  slotidx = first_empty;
694 
695  if (slotidx >= STATISTIC_NUM_SLOTS)
696  ereport(ERROR,
697  (errmsg("maximum number of statistics slots exceeded: %d",
698  slotidx + 1)));
699 
700  stakind_attnum = Anum_pg_statistic_stakind1 - 1 + slotidx;
701  staop_attnum = Anum_pg_statistic_staop1 - 1 + slotidx;
702  stacoll_attnum = Anum_pg_statistic_stacoll1 - 1 + slotidx;
703 
704  if (DatumGetInt16(values[stakind_attnum]) != stakind)
705  {
706  values[stakind_attnum] = Int16GetDatum(stakind);
707  replaces[stakind_attnum] = true;
708  }
709  if (DatumGetObjectId(values[staop_attnum]) != staop)
710  {
711  values[staop_attnum] = ObjectIdGetDatum(staop);
712  replaces[staop_attnum] = true;
713  }
714  if (DatumGetObjectId(values[stacoll_attnum]) != stacoll)
715  {
716  values[stacoll_attnum] = ObjectIdGetDatum(stacoll);
717  replaces[stacoll_attnum] = true;
718  }
719  if (!stanumbers_isnull)
720  {
721  values[Anum_pg_statistic_stanumbers1 - 1 + slotidx] = stanumbers;
722  nulls[Anum_pg_statistic_stanumbers1 - 1 + slotidx] = false;
723  replaces[Anum_pg_statistic_stanumbers1 - 1 + slotidx] = true;
724  }
725  if (!stavalues_isnull)
726  {
727  values[Anum_pg_statistic_stavalues1 - 1 + slotidx] = stavalues;
728  nulls[Anum_pg_statistic_stavalues1 - 1 + slotidx] = false;
729  replaces[Anum_pg_statistic_stavalues1 - 1 + slotidx] = true;
730  }
731 }
static Oid DatumGetObjectId(Datum X)
Definition: postgres.h:242
static int16 DatumGetInt16(Datum X)
Definition: postgres.h:162

References DatumGetInt16(), DatumGetObjectId(), ereport, errmsg(), ERROR, Int16GetDatum(), ObjectIdGetDatum(), STATISTIC_NUM_SLOTS, and values.

Referenced by attribute_statistics_update().

◆ text_to_stavalues()

static Datum text_to_stavalues ( const char *  staname,
FmgrInfo array_in,
Datum  d,
Oid  typid,
int32  typmod,
int  elevel,
bool ok 
)
static

Definition at line 615 of file attribute_stats.c.

617 {
618  LOCAL_FCINFO(fcinfo, 8);
619  char *s;
620  Datum result;
621  ErrorSaveContext escontext = {T_ErrorSaveContext};
622 
623  escontext.details_wanted = true;
624 
625  s = TextDatumGetCString(d);
626 
628  (Node *) &escontext, NULL);
629 
630  fcinfo->args[0].value = CStringGetDatum(s);
631  fcinfo->args[0].isnull = false;
632  fcinfo->args[1].value = ObjectIdGetDatum(typid);
633  fcinfo->args[1].isnull = false;
634  fcinfo->args[2].value = Int32GetDatum(typmod);
635  fcinfo->args[2].isnull = false;
636 
637  result = FunctionCallInvoke(fcinfo);
638 
639  pfree(s);
640 
641  if (escontext.error_occurred)
642  {
643  if (elevel != ERROR)
644  escontext.error_data->elevel = elevel;
645  ThrowErrorData(escontext.error_data);
646  *ok = false;
647  return (Datum) 0;
648  }
649 
651  {
652  ereport(elevel,
653  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
654  errmsg("\"%s\" array cannot contain NULL values", staname)));
655  *ok = false;
656  return (Datum) 0;
657  }
658 
659  *ok = true;
660 
661  return result;
662 }
#define DatumGetArrayTypeP(X)
Definition: array.h:261
bool array_contains_nulls(ArrayType *array)
Definition: arrayfuncs.c:3767
Datum array_in(PG_FUNCTION_ARGS)
Definition: arrayfuncs.c:179
#define TextDatumGetCString(d)
Definition: builtins.h:98
void ThrowErrorData(ErrorData *edata)
Definition: elog.c:1895
#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo)
Definition: fmgr.h:150
#define LOCAL_FCINFO(name, nargs)
Definition: fmgr.h:110
#define FunctionCallInvoke(fcinfo)
Definition: fmgr.h:172
void pfree(void *pointer)
Definition: mcxt.c:1521
static Datum CStringGetDatum(const char *X)
Definition: postgres.h:350
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:212
int elevel
Definition: elog.h:429
bool details_wanted
Definition: miscnodes.h:48
ErrorData * error_data
Definition: miscnodes.h:49
bool error_occurred
Definition: miscnodes.h:47

References array_contains_nulls(), array_in(), CStringGetDatum(), DatumGetArrayTypeP, ErrorSaveContext::details_wanted, ErrorData::elevel, ereport, errcode(), errmsg(), ERROR, ErrorSaveContext::error_data, ErrorSaveContext::error_occurred, FunctionCallInvoke, InitFunctionCallInfoData, Int32GetDatum(), InvalidOid, LOCAL_FCINFO, ObjectIdGetDatum(), pfree(), TextDatumGetCString, and ThrowErrorData().

Referenced by attribute_statistics_update().

◆ upsert_pg_statistic()

static void upsert_pg_statistic ( Relation  starel,
HeapTuple  oldtup,
Datum values,
bool nulls,
bool replaces 
)
static

Definition at line 737 of file attribute_stats.c.

739 {
740  HeapTuple newtup;
741 
742  if (HeapTupleIsValid(oldtup))
743  {
744  newtup = heap_modify_tuple(oldtup, RelationGetDescr(starel),
745  values, nulls, replaces);
746  CatalogTupleUpdate(starel, &newtup->t_self, newtup);
747  }
748  else
749  {
750  newtup = heap_form_tuple(RelationGetDescr(starel), values, nulls);
751  CatalogTupleInsert(starel, newtup);
752  }
753 
754  heap_freetuple(newtup);
755 }
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, const Datum *replValues, const bool *replIsnull, const bool *doReplace)
Definition: heaptuple.c:1209
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
Definition: heaptuple.c:1116
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1434
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:313
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:233

References CatalogTupleInsert(), CatalogTupleUpdate(), heap_form_tuple(), heap_freetuple(), heap_modify_tuple(), HeapTupleIsValid, RelationGetDescr, HeapTupleData::t_self, and values.

Referenced by attribute_statistics_update().

Variable Documentation

◆ attarginfo

struct StatsArgInfo attarginfo[]
static
Initial value:
=
{
[ATTRELATION_ARG] = {"relation", REGCLASSOID},
[ATTNAME_ARG] = {"attname", NAMEOID},
[INHERITED_ARG] = {"inherited", BOOLOID},
[NULL_FRAC_ARG] = {"null_frac", FLOAT4OID},
[AVG_WIDTH_ARG] = {"avg_width", INT4OID},
[N_DISTINCT_ARG] = {"n_distinct", FLOAT4OID},
[MOST_COMMON_VALS_ARG] = {"most_common_vals", TEXTOID},
[MOST_COMMON_FREQS_ARG] = {"most_common_freqs", FLOAT4ARRAYOID},
[HISTOGRAM_BOUNDS_ARG] = {"histogram_bounds", TEXTOID},
[CORRELATION_ARG] = {"correlation", FLOAT4OID},
[MOST_COMMON_ELEMS_ARG] = {"most_common_elems", TEXTOID},
[MOST_COMMON_ELEM_FREQS_ARG] = {"most_common_elem_freqs", FLOAT4ARRAYOID},
[ELEM_COUNT_HISTOGRAM_ARG] = {"elem_count_histogram", FLOAT4ARRAYOID},
[RANGE_LENGTH_HISTOGRAM_ARG] = {"range_length_histogram", TEXTOID},
[RANGE_EMPTY_FRAC_ARG] = {"range_empty_frac", FLOAT4OID},
[RANGE_BOUNDS_HISTOGRAM_ARG] = {"range_bounds_histogram", TEXTOID},
}

Definition at line 1 of file attribute_stats.c.

Referenced by attribute_statistics_update(), and pg_clear_attribute_stats().