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)
 
Datum pg_restore_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  if (RecoveryInProgress())
159  ereport(ERROR,
160  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
161  errmsg("recovery is in progress"),
162  errhint("Statistics cannot be modified during recovery.")));
163 
164  /* lock before looking up attribute */
166 
169  attnum = get_attnum(reloid, NameStr(*attname));
170 
171  if (attnum < 0)
172  ereport(ERROR,
173  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
174  errmsg("cannot modify statistics on system column \"%s\"",
175  NameStr(*attname))));
176 
177  if (attnum == InvalidAttrNumber)
178  ereport(ERROR,
179  (errcode(ERRCODE_UNDEFINED_COLUMN),
180  errmsg("column \"%s\" of relation \"%s\" does not exist",
181  NameStr(*attname), get_rel_name(reloid))));
182 
184  inherited = PG_GETARG_BOOL(INHERITED_ARG);
185 
186  /*
187  * Check argument sanity. If some arguments are unusable, emit at elevel
188  * and set the corresponding argument to NULL in fcinfo.
189  */
190 
192  elevel))
193  {
194  do_mcv = false;
195  result = false;
196  }
197 
199  elevel))
200  {
201  do_mcelem = false;
202  result = false;
203  }
205  elevel))
206  {
207  do_dechist = false;
208  result = false;
209  }
210 
211  if (!stats_check_arg_pair(fcinfo, attarginfo,
213  elevel))
214  {
215  do_mcv = false;
216  result = false;
217  }
218 
219  if (!stats_check_arg_pair(fcinfo, attarginfo,
222  {
223  do_mcelem = false;
224  result = false;
225  }
226 
227  if (!stats_check_arg_pair(fcinfo, attarginfo,
229  RANGE_EMPTY_FRAC_ARG, elevel))
230  {
231  do_range_length_histogram = false;
232  result = false;
233  }
234 
235  /* derive information from attribute */
236  get_attr_stat_type(reloid, attnum, elevel,
237  &atttypid, &atttypmod,
238  &atttyptype, &atttypcoll,
239  &eq_opr, &lt_opr);
240 
241  /* if needed, derive element type */
242  if (do_mcelem || do_dechist)
243  {
244  if (!get_elem_stat_type(atttypid, atttyptype, elevel,
245  &elemtypid, &elem_eq_opr))
246  {
247  ereport(elevel,
248  (errmsg("unable to determine element type of attribute \"%s\"", NameStr(*attname)),
249  errdetail("Cannot set STATISTIC_KIND_MCELEM or STATISTIC_KIND_DECHIST.")));
250  elemtypid = InvalidOid;
251  elem_eq_opr = InvalidOid;
252 
253  do_mcelem = false;
254  do_dechist = false;
255  result = false;
256  }
257  }
258 
259  /* histogram and correlation require less-than operator */
260  if ((do_histogram || do_correlation) && !OidIsValid(lt_opr))
261  {
262  ereport(elevel,
263  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
264  errmsg("could not determine less-than operator for attribute \"%s\"", NameStr(*attname)),
265  errdetail("Cannot set STATISTIC_KIND_HISTOGRAM or STATISTIC_KIND_CORRELATION.")));
266 
267  do_histogram = false;
268  do_correlation = false;
269  result = false;
270  }
271 
272  /* only range types can have range stats */
273  if ((do_range_length_histogram || do_bounds_histogram) &&
274  !(atttyptype == TYPTYPE_RANGE || atttyptype == TYPTYPE_MULTIRANGE))
275  {
276  ereport(elevel,
277  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
278  errmsg("attribute \"%s\" is not a range type", NameStr(*attname)),
279  errdetail("Cannot set STATISTIC_KIND_RANGE_LENGTH_HISTOGRAM or STATISTIC_KIND_BOUNDS_HISTOGRAM.")));
280 
281  do_bounds_histogram = false;
282  do_range_length_histogram = false;
283  result = false;
284  }
285 
286  fmgr_info(F_ARRAY_IN, &array_in_fn);
287 
288  starel = table_open(StatisticRelationId, RowExclusiveLock);
289 
290  statup = SearchSysCache3(STATRELATTINH, reloid, attnum, inherited);
291 
292  /* initialize from existing tuple if exists */
293  if (HeapTupleIsValid(statup))
294  heap_deform_tuple(statup, RelationGetDescr(starel), values, nulls);
295  else
296  init_empty_stats_tuple(reloid, attnum, inherited, values, nulls,
297  replaces);
298 
299  /* if specified, set to argument values */
301  {
302  values[Anum_pg_statistic_stanullfrac - 1] = PG_GETARG_DATUM(NULL_FRAC_ARG);
303  replaces[Anum_pg_statistic_stanullfrac - 1] = true;
304  }
306  {
307  values[Anum_pg_statistic_stawidth - 1] = PG_GETARG_DATUM(AVG_WIDTH_ARG);
308  replaces[Anum_pg_statistic_stawidth - 1] = true;
309  }
311  {
312  values[Anum_pg_statistic_stadistinct - 1] = PG_GETARG_DATUM(N_DISTINCT_ARG);
313  replaces[Anum_pg_statistic_stadistinct - 1] = true;
314  }
315 
316  /* STATISTIC_KIND_MCV */
317  if (do_mcv)
318  {
319  bool converted;
321  Datum stavalues = text_to_stavalues("most_common_vals",
322  &array_in_fn,
324  atttypid, atttypmod,
325  elevel, &converted);
326 
327  if (converted)
328  {
329  set_stats_slot(values, nulls, replaces,
330  STATISTIC_KIND_MCV,
331  eq_opr, atttypcoll,
332  stanumbers, false, stavalues, false);
333  }
334  else
335  result = false;
336  }
337 
338  /* STATISTIC_KIND_HISTOGRAM */
339  if (do_histogram)
340  {
341  Datum stavalues;
342  bool converted = false;
343 
344  stavalues = text_to_stavalues("histogram_bounds",
345  &array_in_fn,
347  atttypid, atttypmod, elevel,
348  &converted);
349 
350  if (converted)
351  {
352  set_stats_slot(values, nulls, replaces,
353  STATISTIC_KIND_HISTOGRAM,
354  lt_opr, atttypcoll,
355  0, true, stavalues, false);
356  }
357  else
358  result = false;
359  }
360 
361  /* STATISTIC_KIND_CORRELATION */
362  if (do_correlation)
363  {
365  ArrayType *arry = construct_array_builtin(elems, 1, FLOAT4OID);
366  Datum stanumbers = PointerGetDatum(arry);
367 
368  set_stats_slot(values, nulls, replaces,
369  STATISTIC_KIND_CORRELATION,
370  lt_opr, atttypcoll,
371  stanumbers, false, 0, true);
372  }
373 
374  /* STATISTIC_KIND_MCELEM */
375  if (do_mcelem)
376  {
378  bool converted = false;
379  Datum stavalues;
380 
381  stavalues = text_to_stavalues("most_common_elems",
382  &array_in_fn,
384  elemtypid, atttypmod,
385  elevel, &converted);
386 
387  if (converted)
388  {
389  set_stats_slot(values, nulls, replaces,
390  STATISTIC_KIND_MCELEM,
391  elem_eq_opr, atttypcoll,
392  stanumbers, false, stavalues, false);
393  }
394  else
395  result = false;
396  }
397 
398  /* STATISTIC_KIND_DECHIST */
399  if (do_dechist)
400  {
402 
403  set_stats_slot(values, nulls, replaces,
404  STATISTIC_KIND_DECHIST,
405  elem_eq_opr, atttypcoll,
406  stanumbers, false, 0, true);
407  }
408 
409  /*
410  * STATISTIC_KIND_BOUNDS_HISTOGRAM
411  *
412  * This stakind appears before STATISTIC_KIND_RANGE_LENGTH_HISTOGRAM even
413  * though it is numerically greater, and all other stakinds appear in
414  * numerical order. We duplicate this quirk for consistency.
415  */
416  if (do_bounds_histogram)
417  {
418  bool converted = false;
419  Datum stavalues;
420 
421  stavalues = text_to_stavalues("range_bounds_histogram",
422  &array_in_fn,
424  atttypid, atttypmod,
425  elevel, &converted);
426 
427  if (converted)
428  {
429  set_stats_slot(values, nulls, replaces,
430  STATISTIC_KIND_BOUNDS_HISTOGRAM,
432  0, true, stavalues, false);
433  }
434  else
435  result = false;
436  }
437 
438  /* STATISTIC_KIND_RANGE_LENGTH_HISTOGRAM */
439  if (do_range_length_histogram)
440  {
441  /* The anyarray is always a float8[] for this stakind */
443  ArrayType *arry = construct_array_builtin(elems, 1, FLOAT4OID);
444  Datum stanumbers = PointerGetDatum(arry);
445 
446  bool converted = false;
447  Datum stavalues;
448 
449  stavalues = text_to_stavalues("range_length_histogram",
450  &array_in_fn,
452  FLOAT8OID, 0, elevel, &converted);
453 
454  if (converted)
455  {
456  set_stats_slot(values, nulls, replaces,
457  STATISTIC_KIND_RANGE_LENGTH_HISTOGRAM,
458  Float8LessOperator, InvalidOid,
459  stanumbers, false, stavalues, false);
460  }
461  else
462  result = false;
463  }
464 
465  upsert_pg_statistic(starel, statup, values, nulls, replaces);
466 
467  if (HeapTupleIsValid(statup))
468  ReleaseSysCache(statup);
469  table_close(starel, RowExclusiveLock);
470 
471  return result;
472 }
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:151
#define NameStr(name)
Definition: c.h:700
int32_t int32
Definition: c.h:481
#define OidIsValid(objectId)
Definition: c.h:729
int errdetail(const char *fmt,...)
Definition: elog.c:1203
int errhint(const char *fmt,...)
Definition: elog.c:1317
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:52
void stats_check_required_arg(FunctionCallInfo fcinfo, struct StatsArgInfo *arginfo, int argnum)
Definition: stat_utils.c:33
bool stats_check_arg_pair(FunctionCallInfo fcinfo, struct StatsArgInfo *arginfo, int argnum1, int argnum2, int elevel)
Definition: stat_utils.c:93
void stats_lock_check_privileges(Oid reloid)
Definition: stat_utils.c:127
Definition: fmgr.h:57
Definition: c.h:695
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
bool RecoveryInProgress(void)
Definition: xlog.c:6334

References attarginfo, attname, ATTNAME_ARG, attnum, ATTRELATION_ARG, AVG_WIDTH_ARG, construct_array_builtin(), CORRELATION_ARG, ELEM_COUNT_HISTOGRAM_ARG, ereport, errcode(), errdetail(), errhint(), 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, RecoveryInProgress(), 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_restore_attribute_stats(), and pg_set_attribute_stats().

◆ delete_pg_statistic()

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

Definition at line 776 of file attribute_stats.c.

777 {
778  Relation sd = table_open(StatisticRelationId, RowExclusiveLock);
779  HeapTuple oldtup;
780  bool result = false;
781 
782  /* Is there already a pg_statistic tuple for this attribute? */
783  oldtup = SearchSysCache3(STATRELATTINH,
784  ObjectIdGetDatum(reloid),
786  BoolGetDatum(stainherit));
787 
788  if (HeapTupleIsValid(oldtup))
789  {
790  CatalogTupleDelete(sd, &oldtup->t_self);
791  ReleaseSysCache(oldtup);
792  result = true;
793  }
794 
796 
798 
799  return result;
800 }
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
void CommandCounterIncrement(void)
Definition: xact.c:1099

References attnum, BoolGetDatum(), CatalogTupleDelete(), CommandCounterIncrement(), 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 481 of file attribute_stats.c.

482 {
483  if ((rel->rd_rel->relkind == RELKIND_INDEX
484  || (rel->rd_rel->relkind == RELKIND_PARTITIONED_INDEX))
485  && (rel->rd_indexprs != NIL)
486  && (rel->rd_index->indkey.values[attnum - 1] == 0))
487  {
488  ListCell *indexpr_item = list_head(rel->rd_indexprs);
489 
490  for (int i = 0; i < attnum - 1; i++)
491  if (rel->rd_index->indkey.values[i] == 0)
492  indexpr_item = lnext(rel->rd_indexprs, indexpr_item);
493 
494  if (indexpr_item == NULL) /* shouldn't happen */
495  elog(ERROR, "too few entries in indexprs list");
496 
497  return (Node *) lfirst(indexpr_item);
498  }
499  return NULL;
500 }
#define elog(elevel,...)
Definition: elog.h:225
int i
Definition: isn.c:72
#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 506 of file attribute_stats.c.

510 {
511  Relation rel = relation_open(reloid, AccessShareLock);
512  Form_pg_attribute attr;
513  HeapTuple atup;
514  Node *expr;
515  TypeCacheEntry *typcache;
516 
517  atup = SearchSysCache2(ATTNUM, ObjectIdGetDatum(reloid),
519 
520  /* Attribute not found */
521  if (!HeapTupleIsValid(atup))
522  ereport(ERROR,
523  (errcode(ERRCODE_UNDEFINED_COLUMN),
524  errmsg("attribute %d of relation \"%s\" does not exist",
526 
527  attr = (Form_pg_attribute) GETSTRUCT(atup);
528 
529  if (attr->attisdropped)
530  ereport(ERROR,
531  (errcode(ERRCODE_UNDEFINED_COLUMN),
532  errmsg("attribute %d of relation \"%s\" does not exist",
534 
535  expr = get_attr_expr(rel, attr->attnum);
536 
537  /*
538  * When analyzing an expression index, believe the expression tree's type
539  * not the column datatype --- the latter might be the opckeytype storage
540  * type of the opclass, which is not interesting for our purposes. This
541  * mimics the behvior of examine_attribute().
542  */
543  if (expr == NULL)
544  {
545  *atttypid = attr->atttypid;
546  *atttypmod = attr->atttypmod;
547  *atttypcoll = attr->attcollation;
548  }
549  else
550  {
551  *atttypid = exprType(expr);
552  *atttypmod = exprTypmod(expr);
553 
554  if (OidIsValid(attr->attcollation))
555  *atttypcoll = attr->attcollation;
556  else
557  *atttypcoll = exprCollation(expr);
558  }
559  ReleaseSysCache(atup);
560 
561  /*
562  * If it's a multirange, step down to the range type, as is done by
563  * multirange_typanalyze().
564  */
565  if (type_is_multirange(*atttypid))
566  *atttypid = get_multirange_range(*atttypid);
567 
568  /* finds the right operators even if atttypid is a domain */
569  typcache = lookup_type_cache(*atttypid, TYPECACHE_LT_OPR | TYPECACHE_EQ_OPR);
570  *atttyptype = typcache->typtype;
571  *eq_opr = typcache->eq_opr;
572  *lt_opr = typcache->lt_opr;
573 
574  /*
575  * Special case: collation for tsvector is DEFAULT_COLLATION_OID. See
576  * compute_tsvector_stats().
577  */
578  if (*atttypid == TSVECTOROID)
579  *atttypcoll = DEFAULT_COLLATION_OID;
580 
581  relation_close(rel, NoLock);
582 }
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:386
#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 588 of file attribute_stats.c.

590 {
591  TypeCacheEntry *elemtypcache;
592 
593  if (atttypid == TSVECTOROID)
594  {
595  /*
596  * Special case: element type for tsvector is text. See
597  * compute_tsvector_stats().
598  */
599  *elemtypid = TEXTOID;
600  }
601  else
602  {
603  /* find underlying element type through any domain */
604  *elemtypid = get_base_element_type(atttypid);
605  }
606 
607  if (!OidIsValid(*elemtypid))
608  return false;
609 
610  /* finds the right operator even if elemtypid is a domain */
611  elemtypcache = lookup_type_cache(*elemtypid, TYPECACHE_EQ_OPR);
612  if (!OidIsValid(elemtypcache->eq_opr))
613  return false;
614 
615  *elem_eq_opr = elemtypcache->eq_opr;
616 
617  return true;
618 }
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 806 of file attribute_stats.c.

808 {
809  memset(nulls, true, sizeof(bool) * Natts_pg_statistic);
810  memset(replaces, true, sizeof(bool) * Natts_pg_statistic);
811 
812  /* must initialize non-NULL attributes */
813 
814  values[Anum_pg_statistic_starelid - 1] = ObjectIdGetDatum(reloid);
815  nulls[Anum_pg_statistic_starelid - 1] = false;
816  values[Anum_pg_statistic_staattnum - 1] = Int16GetDatum(attnum);
817  nulls[Anum_pg_statistic_staattnum - 1] = false;
818  values[Anum_pg_statistic_stainherit - 1] = BoolGetDatum(inherited);
819  nulls[Anum_pg_statistic_stainherit - 1] = false;
820 
821  values[Anum_pg_statistic_stanullfrac - 1] = DEFAULT_NULL_FRAC;
822  nulls[Anum_pg_statistic_stanullfrac - 1] = false;
823  values[Anum_pg_statistic_stawidth - 1] = DEFAULT_AVG_WIDTH;
824  nulls[Anum_pg_statistic_stawidth - 1] = false;
825  values[Anum_pg_statistic_stadistinct - 1] = DEFAULT_N_DISTINCT;
826  nulls[Anum_pg_statistic_stadistinct - 1] = false;
827 
828  /* initialize stakind, staop, and stacoll slots */
829  for (int slotnum = 0; slotnum < STATISTIC_NUM_SLOTS; slotnum++)
830  {
831  values[Anum_pg_statistic_stakind1 + slotnum - 1] = (Datum) 0;
832  nulls[Anum_pg_statistic_stakind1 + slotnum - 1] = false;
833  values[Anum_pg_statistic_staop1 + slotnum - 1] = InvalidOid;
834  nulls[Anum_pg_statistic_staop1 + slotnum - 1] = false;
835  values[Anum_pg_statistic_stacoll1 + slotnum - 1] = InvalidOid;
836  nulls[Anum_pg_statistic_stacoll1 + slotnum - 1] = false;
837  }
838 }
#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 871 of file attribute_stats.c.

872 {
873  Oid reloid;
874  Name attname;
876  bool inherited;
877 
879  reloid = PG_GETARG_OID(ATTRELATION_ARG);
880 
881  if (RecoveryInProgress())
882  ereport(ERROR,
883  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
884  errmsg("recovery is in progress"),
885  errhint("Statistics cannot be modified during recovery.")));
886 
888 
891  attnum = get_attnum(reloid, NameStr(*attname));
892 
893  if (attnum < 0)
894  ereport(ERROR,
895  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
896  errmsg("cannot clear statistics on system column \"%s\"",
897  NameStr(*attname))));
898 
899  if (attnum == InvalidAttrNumber)
900  ereport(ERROR,
901  (errcode(ERRCODE_UNDEFINED_COLUMN),
902  errmsg("column \"%s\" of relation \"%s\" does not exist",
903  NameStr(*attname), get_rel_name(reloid))));
904 
906  inherited = PG_GETARG_BOOL(INHERITED_ARG);
907 
908  delete_pg_statistic(reloid, attnum, inherited);
909  PG_RETURN_VOID();
910 }
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(), errhint(), errmsg(), ERROR, get_attnum(), get_rel_name(), INHERITED_ARG, InvalidAttrNumber, NameStr, PG_GETARG_BOOL, PG_GETARG_NAME, PG_GETARG_OID, PG_RETURN_VOID, RecoveryInProgress(), stats_check_required_arg(), and stats_lock_check_privileges().

◆ pg_restore_attribute_stats()

Datum pg_restore_attribute_stats ( PG_FUNCTION_ARGS  )

Definition at line 913 of file attribute_stats.c.

914 {
915  LOCAL_FCINFO(positional_fcinfo, NUM_ATTRIBUTE_STATS_ARGS);
916  bool result = true;
917 
918  InitFunctionCallInfoData(*positional_fcinfo, NULL, NUM_ATTRIBUTE_STATS_ARGS,
919  InvalidOid, NULL, NULL);
920 
921  if (!stats_fill_fcinfo_from_arg_pairs(fcinfo, positional_fcinfo,
923  result = false;
924 
925  if (!attribute_statistics_update(positional_fcinfo, WARNING))
926  result = false;
927 
928  PG_RETURN_BOOL(result);
929 }
static bool attribute_statistics_update(FunctionCallInfo fcinfo, int elevel)
#define WARNING
Definition: elog.h:36
#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo)
Definition: fmgr.h:150
#define LOCAL_FCINFO(name, nargs)
Definition: fmgr.h:110
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359
bool stats_fill_fcinfo_from_arg_pairs(FunctionCallInfo pairs_fcinfo, FunctionCallInfo positional_fcinfo, struct StatsArgInfo *arginfo, int elevel)
Definition: stat_utils.c:217

References attarginfo, attribute_statistics_update(), InitFunctionCallInfoData, InvalidOid, LOCAL_FCINFO, NUM_ATTRIBUTE_STATS_ARGS, PG_RETURN_BOOL, stats_fill_fcinfo_from_arg_pairs(), and WARNING.

◆ pg_set_attribute_stats()

Datum pg_set_attribute_stats ( PG_FUNCTION_ARGS  )

Definition at line 861 of file attribute_stats.c.

862 {
864  PG_RETURN_VOID();
865 }

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 682 of file attribute_stats.c.

686 {
687  int slotidx;
688  int first_empty = -1;
689  AttrNumber stakind_attnum;
690  AttrNumber staop_attnum;
691  AttrNumber stacoll_attnum;
692 
693  /* find existing slot with given stakind */
694  for (slotidx = 0; slotidx < STATISTIC_NUM_SLOTS; slotidx++)
695  {
696  stakind_attnum = Anum_pg_statistic_stakind1 - 1 + slotidx;
697 
698  if (first_empty < 0 &&
699  DatumGetInt16(values[stakind_attnum]) == 0)
700  first_empty = slotidx;
701  if (DatumGetInt16(values[stakind_attnum]) == stakind)
702  break;
703  }
704 
705  if (slotidx >= STATISTIC_NUM_SLOTS && first_empty >= 0)
706  slotidx = first_empty;
707 
708  if (slotidx >= STATISTIC_NUM_SLOTS)
709  ereport(ERROR,
710  (errmsg("maximum number of statistics slots exceeded: %d",
711  slotidx + 1)));
712 
713  stakind_attnum = Anum_pg_statistic_stakind1 - 1 + slotidx;
714  staop_attnum = Anum_pg_statistic_staop1 - 1 + slotidx;
715  stacoll_attnum = Anum_pg_statistic_stacoll1 - 1 + slotidx;
716 
717  if (DatumGetInt16(values[stakind_attnum]) != stakind)
718  {
719  values[stakind_attnum] = Int16GetDatum(stakind);
720  replaces[stakind_attnum] = true;
721  }
722  if (DatumGetObjectId(values[staop_attnum]) != staop)
723  {
724  values[staop_attnum] = ObjectIdGetDatum(staop);
725  replaces[staop_attnum] = true;
726  }
727  if (DatumGetObjectId(values[stacoll_attnum]) != stacoll)
728  {
729  values[stacoll_attnum] = ObjectIdGetDatum(stacoll);
730  replaces[stacoll_attnum] = true;
731  }
732  if (!stanumbers_isnull)
733  {
734  values[Anum_pg_statistic_stanumbers1 - 1 + slotidx] = stanumbers;
735  nulls[Anum_pg_statistic_stanumbers1 - 1 + slotidx] = false;
736  replaces[Anum_pg_statistic_stanumbers1 - 1 + slotidx] = true;
737  }
738  if (!stavalues_isnull)
739  {
740  values[Anum_pg_statistic_stavalues1 - 1 + slotidx] = stavalues;
741  nulls[Anum_pg_statistic_stavalues1 - 1 + slotidx] = false;
742  replaces[Anum_pg_statistic_stavalues1 - 1 + slotidx] = true;
743  }
744 }
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 628 of file attribute_stats.c.

630 {
631  LOCAL_FCINFO(fcinfo, 8);
632  char *s;
633  Datum result;
634  ErrorSaveContext escontext = {T_ErrorSaveContext};
635 
636  escontext.details_wanted = true;
637 
638  s = TextDatumGetCString(d);
639 
641  (Node *) &escontext, NULL);
642 
643  fcinfo->args[0].value = CStringGetDatum(s);
644  fcinfo->args[0].isnull = false;
645  fcinfo->args[1].value = ObjectIdGetDatum(typid);
646  fcinfo->args[1].isnull = false;
647  fcinfo->args[2].value = Int32GetDatum(typmod);
648  fcinfo->args[2].isnull = false;
649 
650  result = FunctionCallInvoke(fcinfo);
651 
652  pfree(s);
653 
654  if (escontext.error_occurred)
655  {
656  if (elevel != ERROR)
657  escontext.error_data->elevel = elevel;
658  ThrowErrorData(escontext.error_data);
659  *ok = false;
660  return (Datum) 0;
661  }
662 
664  {
665  ereport(elevel,
666  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
667  errmsg("\"%s\" array cannot contain NULL values", staname)));
668  *ok = false;
669  return (Datum) 0;
670  }
671 
672  *ok = true;
673 
674  return result;
675 }
#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 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 750 of file attribute_stats.c.

752 {
753  HeapTuple newtup;
754 
755  if (HeapTupleIsValid(oldtup))
756  {
757  newtup = heap_modify_tuple(oldtup, RelationGetDescr(starel),
758  values, nulls, replaces);
759  CatalogTupleUpdate(starel, &newtup->t_self, newtup);
760  }
761  else
762  {
763  newtup = heap_form_tuple(RelationGetDescr(starel), values, nulls);
764  CatalogTupleInsert(starel, newtup);
765  }
766 
767  heap_freetuple(newtup);
768 
770 }
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(), CommandCounterIncrement(), 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(), pg_clear_attribute_stats(), and pg_restore_attribute_stats().