PostgreSQL Source Code git master
stat_utils.c File Reference
#include "postgres.h"
#include "access/htup_details.h"
#include "access/relation.h"
#include "catalog/index.h"
#include "catalog/namespace.h"
#include "catalog/pg_class.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_database.h"
#include "catalog/pg_statistic.h"
#include "funcapi.h"
#include "miscadmin.h"
#include "nodes/nodeFuncs.h"
#include "statistics/stat_utils.h"
#include "storage/lmgr.h"
#include "utils/acl.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
#include "utils/rel.h"
#include "utils/syscache.h"
Include dependency graph for stat_utils.c:

Go to the source code of this file.

Macros

#define DEFAULT_STATATT_NULL_FRAC   Float4GetDatum(0.0) /* stanullfrac */
 
#define DEFAULT_STATATT_AVG_WIDTH
 
#define DEFAULT_STATATT_N_DISTINCT
 

Functions

static Nodestatatt_get_index_expr (Relation rel, int attnum)
 
void stats_check_required_arg (FunctionCallInfo fcinfo, struct StatsArgInfo *arginfo, int argnum)
 
bool stats_check_arg_array (FunctionCallInfo fcinfo, struct StatsArgInfo *arginfo, int argnum)
 
bool stats_check_arg_pair (FunctionCallInfo fcinfo, struct StatsArgInfo *arginfo, int argnum1, int argnum2)
 
void RangeVarCallbackForStats (const RangeVar *relation, Oid relId, Oid oldRelId, void *arg)
 
static int get_arg_by_name (const char *argname, struct StatsArgInfo *arginfo)
 
static bool stats_check_arg_type (const char *argname, Oid argtype, Oid expectedtype)
 
bool stats_fill_fcinfo_from_arg_pairs (FunctionCallInfo pairs_fcinfo, FunctionCallInfo positional_fcinfo, struct StatsArgInfo *arginfo)
 
void statatt_get_type (Oid reloid, AttrNumber attnum, Oid *atttypid, int32 *atttypmod, char *atttyptype, Oid *atttypcoll, Oid *eq_opr, Oid *lt_opr)
 
bool statatt_get_elem_type (Oid atttypid, char atttyptype, Oid *elemtypid, Oid *elem_eq_opr)
 
Datum statatt_build_stavalues (const char *staname, FmgrInfo *array_in, Datum d, Oid typid, int32 typmod, bool *ok)
 
void statatt_set_slot (Datum *values, bool *nulls, bool *replaces, int16 stakind, Oid staop, Oid stacoll, Datum stanumbers, bool stanumbers_isnull, Datum stavalues, bool stavalues_isnull)
 
void statatt_init_empty_tuple (Oid reloid, int16 attnum, bool inherited, Datum *values, bool *nulls, bool *replaces)
 

Macro Definition Documentation

◆ DEFAULT_STATATT_AVG_WIDTH

#define DEFAULT_STATATT_AVG_WIDTH
Value:
Int32GetDatum(0) /* stawidth, same as
* unknown */
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:222

Definition at line 41 of file stat_utils.c.

◆ DEFAULT_STATATT_N_DISTINCT

#define DEFAULT_STATATT_N_DISTINCT
Value:
Float4GetDatum(0.0) /* stadistinct, same as
* unknown */
static Datum Float4GetDatum(float4 X)
Definition: postgres.h:478

Definition at line 42 of file stat_utils.c.

◆ DEFAULT_STATATT_NULL_FRAC

#define DEFAULT_STATATT_NULL_FRAC   Float4GetDatum(0.0) /* stanullfrac */

Definition at line 40 of file stat_utils.c.

Function Documentation

◆ get_arg_by_name()

static int get_arg_by_name ( const char *  argname,
struct StatsArgInfo arginfo 
)
static

Definition at line 261 of file stat_utils.c.

264{
265 int argnum;
266
267 for (argnum = 0; arginfo[argnum].argname != NULL; argnum++)
268 if (pg_strcasecmp(argname, arginfo[argnum].argname) == 0)
269 return argnum;
270
272 (errmsg("unrecognized argument name: \"%s\"", argname)));
273
int errmsg(const char *fmt,...)
Definition: elog.c:1080
#define WARNING
Definition: elog.h:36
#define ereport(elevel,...)
Definition: elog.h:150
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:32
const char * argname
Definition: stat_utils.h:24

References StatsArgInfo::argname, ereport, errmsg(), pg_strcasecmp(), and WARNING.

Referenced by stats_fill_fcinfo_from_arg_pairs().

◆ RangeVarCallbackForStats()

void RangeVarCallbackForStats ( const RangeVar relation,
Oid  relId,
Oid  oldRelId,
void *  arg 
)

Definition at line 141 of file stat_utils.c.

145{
146 Oid *locked_oid = (Oid *) arg;
147 Oid table_oid = relId;
148 HeapTuple tuple;
149 Form_pg_class form;
150 char relkind;
151
152 /*
153 * If we previously locked some other index's heap, and the name we're
154 * looking up no longer refers to that relation, release the now-useless
155 * lock.
156 */
157 if (relId != oldRelId && OidIsValid(*locked_oid))
158 {
160 *locked_oid = InvalidOid;
161 }
162
163 /* If the relation does not exist, there's nothing more to do. */
164 if (!OidIsValid(relId))
165 return;
166
167 /* If the relation does exist, check whether it's an index. */
168 relkind = get_rel_relkind(relId);
169 if (relkind == RELKIND_INDEX ||
170 relkind == RELKIND_PARTITIONED_INDEX)
171 table_oid = IndexGetRelation(relId, false);
172
173 /*
174 * If retrying yields the same OID, there are a couple of extremely
175 * unlikely scenarios we need to handle.
176 */
177 if (relId == oldRelId)
178 {
179 /*
180 * If a previous lookup found an index, but the current lookup did
181 * not, the index was dropped and the OID was reused for something
182 * else between lookups. In theory, we could simply drop our lock on
183 * the index's parent table and proceed, but in the interest of
184 * avoiding complexity, we just error.
185 */
186 if (table_oid == relId && OidIsValid(*locked_oid))
188 (errcode(ERRCODE_UNDEFINED_OBJECT),
189 errmsg("index \"%s\" was concurrently dropped",
190 relation->relname)));
191
192 /*
193 * If the current lookup found an index but a previous lookup either
194 * did not find an index or found one with a different parent
195 * relation, the relation was dropped and the OID was reused for an
196 * index between lookups. RangeVarGetRelidExtended() will have
197 * already locked the index at this point, so we can't just lock the
198 * newly discovered parent table OID without risking deadlock. As
199 * above, we just error in this case.
200 */
201 if (table_oid != relId && table_oid != *locked_oid)
203 (errcode(ERRCODE_UNDEFINED_OBJECT),
204 errmsg("index \"%s\" was concurrently created",
205 relation->relname)));
206 }
207
208 tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(table_oid));
209 if (!HeapTupleIsValid(tuple))
210 elog(ERROR, "cache lookup failed for OID %u", table_oid);
211 form = (Form_pg_class) GETSTRUCT(tuple);
212
213 /* the relkinds that can be used with ANALYZE */
214 switch (form->relkind)
215 {
216 case RELKIND_RELATION:
217 case RELKIND_MATVIEW:
218 case RELKIND_FOREIGN_TABLE:
219 case RELKIND_PARTITIONED_TABLE:
220 break;
221 default:
223 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
224 errmsg("cannot modify statistics for relation \"%s\"",
225 NameStr(form->relname)),
226 errdetail_relkind_not_supported(form->relkind)));
227 }
228
229 if (form->relisshared)
231 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
232 errmsg("cannot modify statistics for shared relation")));
233
234 /* Check permissions */
235 if (!object_ownercheck(DatabaseRelationId, MyDatabaseId, GetUserId()))
236 {
237 AclResult aclresult = pg_class_aclcheck(table_oid,
238 GetUserId(),
240
241 if (aclresult != ACLCHECK_OK)
242 aclcheck_error(aclresult,
243 get_relkind_objtype(form->relkind),
244 NameStr(form->relname));
245 }
246
247 ReleaseSysCache(tuple);
248
249 /* Lock heap before index to avoid deadlock. */
250 if (relId != oldRelId && table_oid != relId)
251 {
253 *locked_oid = table_oid;
AclResult
Definition: acl.h:182
@ ACLCHECK_OK
Definition: acl.h:183
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:2654
bool object_ownercheck(Oid classid, Oid objectid, Oid roleid)
Definition: aclchk.c:4090
AclResult pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4039
#define NameStr(name)
Definition: c.h:771
#define OidIsValid(objectId)
Definition: c.h:794
int errcode(int sqlerrcode)
Definition: elog.c:863
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:226
Oid MyDatabaseId
Definition: globals.c:94
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
static void * GETSTRUCT(const HeapTupleData *tuple)
Definition: htup_details.h:728
Oid IndexGetRelation(Oid indexId, bool missing_ok)
Definition: index.c:3581
void UnlockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:229
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:107
#define ShareUpdateExclusiveLock
Definition: lockdefs.h:39
char get_rel_relkind(Oid relid)
Definition: lsyscache.c:2153
Oid GetUserId(void)
Definition: miscinit.c:469
ObjectType get_relkind_objtype(char relkind)
#define ACL_MAINTAIN
Definition: parsenodes.h:90
void * arg
int errdetail_relkind_not_supported(char relkind)
Definition: pg_class.c:24
FormData_pg_class * Form_pg_class
Definition: pg_class.h:156
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:262
#define InvalidOid
Definition: postgres_ext.h:37
unsigned int Oid
Definition: postgres_ext.h:32
char * relname
Definition: primnodes.h:83
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:264
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:220

References ACL_MAINTAIN, aclcheck_error(), ACLCHECK_OK, arg, elog, ereport, errcode(), errdetail_relkind_not_supported(), errmsg(), ERROR, get_rel_relkind(), get_relkind_objtype(), GETSTRUCT(), GetUserId(), HeapTupleIsValid, IndexGetRelation(), InvalidOid, LockRelationOid(), MyDatabaseId, NameStr, object_ownercheck(), ObjectIdGetDatum(), OidIsValid, pg_class_aclcheck(), ReleaseSysCache(), RangeVar::relname, SearchSysCache1(), ShareUpdateExclusiveLock, and UnlockRelationOid().

Referenced by attribute_statistics_update(), pg_clear_attribute_stats(), and relation_statistics_update().

◆ statatt_build_stavalues()

Datum statatt_build_stavalues ( const char *  staname,
FmgrInfo array_in,
Datum  d,
Oid  typid,
int32  typmod,
bool *  ok 
)

Definition at line 566 of file stat_utils.c.

570{
571 LOCAL_FCINFO(fcinfo, 8);
572 char *s;
573 Datum result;
574 ErrorSaveContext escontext = {T_ErrorSaveContext};
575
576 escontext.details_wanted = true;
577
578 s = TextDatumGetCString(d);
579
581 (Node *) &escontext, NULL);
582
583 fcinfo->args[0].value = CStringGetDatum(s);
584 fcinfo->args[0].isnull = false;
585 fcinfo->args[1].value = ObjectIdGetDatum(typid);
586 fcinfo->args[1].isnull = false;
587 fcinfo->args[2].value = Int32GetDatum(typmod);
588 fcinfo->args[2].isnull = false;
589
590 result = FunctionCallInvoke(fcinfo);
591
592 pfree(s);
593
594 if (escontext.error_occurred)
595 {
596 escontext.error_data->elevel = WARNING;
597 ThrowErrorData(escontext.error_data);
598 *ok = false;
599 return (Datum) 0;
600 }
601
603 {
605 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
606 errmsg("\"%s\" array must not contain null values", staname)));
607 *ok = false;
608 return (Datum) 0;
609 }
610
611 *ok = true;
612
#define DatumGetArrayTypeP(X)
Definition: array.h:261
bool array_contains_nulls(const ArrayType *array)
Definition: arrayfuncs.c:3768
Datum array_in(PG_FUNCTION_ARGS)
Definition: arrayfuncs.c:180
#define TextDatumGetCString(d)
Definition: builtins.h:98
void ThrowErrorData(ErrorData *edata)
Definition: elog.c:1912
#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:1616
uint64_t Datum
Definition: postgres.h:70
static Datum CStringGetDatum(const char *X)
Definition: postgres.h:380
int elevel
Definition: elog.h:421
bool details_wanted
Definition: miscnodes.h:48
ErrorData * error_data
Definition: miscnodes.h:49
bool error_occurred
Definition: miscnodes.h:47
Definition: nodes.h:135

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

Referenced by attribute_statistics_update().

◆ statatt_get_elem_type()

bool statatt_get_elem_type ( Oid  atttypid,
char  atttyptype,
Oid elemtypid,
Oid elem_eq_opr 
)

Definition at line 522 of file stat_utils.c.

526{
527 TypeCacheEntry *elemtypcache;
528
529 if (atttypid == TSVECTOROID)
530 {
531 /*
532 * Special case: element type for tsvector is text. See
533 * compute_tsvector_stats().
534 */
535 *elemtypid = TEXTOID;
536 }
537 else
538 {
539 /* find underlying element type through any domain */
540 *elemtypid = get_base_element_type(atttypid);
541 }
542
543 if (!OidIsValid(*elemtypid))
544 return false;
545
546 /* finds the right operator even if elemtypid is a domain */
547 elemtypcache = lookup_type_cache(*elemtypid, TYPECACHE_EQ_OPR);
548 if (!OidIsValid(elemtypcache->eq_opr))
549 return false;
550
551 *elem_eq_opr = elemtypcache->eq_opr;
552
Oid get_base_element_type(Oid typid)
Definition: lsyscache.c:2982
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:386
#define TYPECACHE_EQ_OPR
Definition: typcache.h:138

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

Referenced by attribute_statistics_update().

◆ statatt_get_index_expr()

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

Definition at line 302 of file stat_utils.c.

305{
306 List *index_exprs;
307 ListCell *indexpr_item;
308
309 /* relation is not an index */
310 if (rel->rd_rel->relkind != RELKIND_INDEX &&
311 rel->rd_rel->relkind != RELKIND_PARTITIONED_INDEX)
312 return NULL;
313
314 index_exprs = RelationGetIndexExpressions(rel);
315
316 /* index has no expressions to give */
317 if (index_exprs == NIL)
318 return NULL;
319
320 /*
321 * The index's attnum points directly to a relation attnum, hence it is
322 * not an expression attribute.
323 */
324 if (rel->rd_index->indkey.values[attnum - 1] != 0)
325 return NULL;
326
327 indexpr_item = list_head(rel->rd_indexprs);
328
329 for (int i = 0; i < attnum - 1; i++)
330 if (rel->rd_index->indkey.values[i] == 0)
331 indexpr_item = lnext(rel->rd_indexprs, indexpr_item);
332
333 if (indexpr_item == NULL) /* shouldn't happen */
334 elog(ERROR, "too few entries in indexprs list");
335
int i
Definition: isn.c:77
int16 attnum
Definition: pg_attribute.h:74
#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
List * RelationGetIndexExpressions(Relation relation)
Definition: relcache.c:5092
Definition: pg_list.h:54
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, RelationData::rd_rel, and RelationGetIndexExpressions().

Referenced by statatt_get_type().

◆ statatt_get_type()

void statatt_get_type ( Oid  reloid,
AttrNumber  attnum,
Oid atttypid,
int32 atttypmod,
char *  atttyptype,
Oid atttypcoll,
Oid eq_opr,
Oid lt_opr 
)

Definition at line 436 of file stat_utils.c.

442{
445 HeapTuple atup;
446 Node *expr;
447 TypeCacheEntry *typcache;
448
449 atup = SearchSysCache2(ATTNUM, ObjectIdGetDatum(reloid),
451
452 /* Attribute not found */
453 if (!HeapTupleIsValid(atup))
455 (errcode(ERRCODE_UNDEFINED_COLUMN),
456 errmsg("column %d of relation \"%s\" does not exist",
458
459 attr = (Form_pg_attribute) GETSTRUCT(atup);
460
461 if (attr->attisdropped)
463 (errcode(ERRCODE_UNDEFINED_COLUMN),
464 errmsg("column %d of relation \"%s\" does not exist",
466
467 expr = statatt_get_index_expr(rel, attr->attnum);
468
469 /*
470 * When analyzing an expression index, believe the expression tree's type
471 * not the column datatype --- the latter might be the opckeytype storage
472 * type of the opclass, which is not interesting for our purposes. This
473 * mimics the behavior of examine_attribute().
474 */
475 if (expr == NULL)
476 {
477 *atttypid = attr->atttypid;
478 *atttypmod = attr->atttypmod;
479 *atttypcoll = attr->attcollation;
480 }
481 else
482 {
483 *atttypid = exprType(expr);
484 *atttypmod = exprTypmod(expr);
485
486 if (OidIsValid(attr->attcollation))
487 *atttypcoll = attr->attcollation;
488 else
489 *atttypcoll = exprCollation(expr);
490 }
491 ReleaseSysCache(atup);
492
493 /*
494 * If it's a multirange, step down to the range type, as is done by
495 * multirange_typanalyze().
496 */
497 if (type_is_multirange(*atttypid))
498 *atttypid = get_multirange_range(*atttypid);
499
500 /* finds the right operators even if atttypid is a domain */
501 typcache = lookup_type_cache(*atttypid, TYPECACHE_LT_OPR | TYPECACHE_EQ_OPR);
502 *atttyptype = typcache->typtype;
503 *eq_opr = typcache->eq_opr;
504 *lt_opr = typcache->lt_opr;
505
506 /*
507 * Special case: collation for tsvector is DEFAULT_COLLATION_OID. See
508 * compute_tsvector_stats().
509 */
510 if (*atttypid == TSVECTOROID)
511 *atttypcoll = DEFAULT_COLLATION_OID;
512
#define AccessShareLock
Definition: lockdefs.h:36
Oid get_multirange_range(Oid multirangeOid)
Definition: lsyscache.c:3633
bool type_is_multirange(Oid typid)
Definition: lsyscache.c:2848
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
int32 exprTypmod(const Node *expr)
Definition: nodeFuncs.c:301
Oid exprCollation(const Node *expr)
Definition: nodeFuncs.c:821
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:202
static Datum Int16GetDatum(int16 X)
Definition: postgres.h:182
#define RelationGetRelationName(relation)
Definition: rel.h:549
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: relation.c:47
static Node * statatt_get_index_expr(Relation rel, int attnum)
Definition: stat_utils.c:302
char typtype
Definition: typcache.h:43
HeapTuple SearchSysCache2(int cacheId, Datum key1, Datum key2)
Definition: syscache.c:230
#define TYPECACHE_LT_OPR
Definition: typcache.h:139

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

Referenced by attribute_statistics_update().

◆ statatt_init_empty_tuple()

void statatt_init_empty_tuple ( Oid  reloid,
int16  attnum,
bool  inherited,
Datum values,
bool *  nulls,
bool *  replaces 
)

Definition at line 712 of file stat_utils.c.

716{
717 memset(nulls, true, sizeof(bool) * Natts_pg_statistic);
718 memset(replaces, true, sizeof(bool) * Natts_pg_statistic);
719
720 /* This must initialize non-NULL attributes */
721 values[Anum_pg_statistic_starelid - 1] = ObjectIdGetDatum(reloid);
722 nulls[Anum_pg_statistic_starelid - 1] = false;
723 values[Anum_pg_statistic_staattnum - 1] = Int16GetDatum(attnum);
724 nulls[Anum_pg_statistic_staattnum - 1] = false;
725 values[Anum_pg_statistic_stainherit - 1] = BoolGetDatum(inherited);
726 nulls[Anum_pg_statistic_stainherit - 1] = false;
727
728 values[Anum_pg_statistic_stanullfrac - 1] = DEFAULT_STATATT_NULL_FRAC;
729 nulls[Anum_pg_statistic_stanullfrac - 1] = false;
730 values[Anum_pg_statistic_stawidth - 1] = DEFAULT_STATATT_AVG_WIDTH;
731 nulls[Anum_pg_statistic_stawidth - 1] = false;
732 values[Anum_pg_statistic_stadistinct - 1] = DEFAULT_STATATT_N_DISTINCT;
733 nulls[Anum_pg_statistic_stadistinct - 1] = false;
734
735 /* initialize stakind, staop, and stacoll slots */
736 for (int slotnum = 0; slotnum < STATISTIC_NUM_SLOTS; slotnum++)
737 {
738 values[Anum_pg_statistic_stakind1 + slotnum - 1] = (Datum) 0;
739 nulls[Anum_pg_statistic_stakind1 + slotnum - 1] = false;
740 values[Anum_pg_statistic_staop1 + slotnum - 1] = ObjectIdGetDatum(InvalidOid);
741 nulls[Anum_pg_statistic_staop1 + slotnum - 1] = false;
742 values[Anum_pg_statistic_stacoll1 + slotnum - 1] = ObjectIdGetDatum(InvalidOid);
743 nulls[Anum_pg_statistic_stacoll1 + slotnum - 1] = false;
static Datum values[MAXATTR]
Definition: bootstrap.c:155
#define STATISTIC_NUM_SLOTS
Definition: pg_statistic.h:127
static Datum BoolGetDatum(bool X)
Definition: postgres.h:112
#define DEFAULT_STATATT_NULL_FRAC
Definition: stat_utils.c:40
#define DEFAULT_STATATT_AVG_WIDTH
Definition: stat_utils.c:41
#define DEFAULT_STATATT_N_DISTINCT
Definition: stat_utils.c:42

References attnum, BoolGetDatum(), DEFAULT_STATATT_AVG_WIDTH, DEFAULT_STATATT_N_DISTINCT, DEFAULT_STATATT_NULL_FRAC, Int16GetDatum(), InvalidOid, ObjectIdGetDatum(), STATISTIC_NUM_SLOTS, and values.

Referenced by attribute_statistics_update().

◆ statatt_set_slot()

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

Definition at line 634 of file stat_utils.c.

640{
641 int slotidx;
642 int first_empty = -1;
643 AttrNumber stakind_attnum;
644 AttrNumber staop_attnum;
645 AttrNumber stacoll_attnum;
646
647 /* find existing slot with given stakind */
648 for (slotidx = 0; slotidx < STATISTIC_NUM_SLOTS; slotidx++)
649 {
650 stakind_attnum = Anum_pg_statistic_stakind1 - 1 + slotidx;
651
652 if (first_empty < 0 &&
653 DatumGetInt16(values[stakind_attnum]) == 0)
654 first_empty = slotidx;
655 if (DatumGetInt16(values[stakind_attnum]) == stakind)
656 break;
657 }
658
659 if (slotidx >= STATISTIC_NUM_SLOTS && first_empty >= 0)
660 slotidx = first_empty;
661
662 if (slotidx >= STATISTIC_NUM_SLOTS)
664 (errmsg("maximum number of statistics slots exceeded: %d",
665 slotidx + 1)));
666
667 stakind_attnum = Anum_pg_statistic_stakind1 - 1 + slotidx;
668 staop_attnum = Anum_pg_statistic_staop1 - 1 + slotidx;
669 stacoll_attnum = Anum_pg_statistic_stacoll1 - 1 + slotidx;
670
671 if (DatumGetInt16(values[stakind_attnum]) != stakind)
672 {
673 values[stakind_attnum] = Int16GetDatum(stakind);
674 replaces[stakind_attnum] = true;
675 }
676 if (DatumGetObjectId(values[staop_attnum]) != staop)
677 {
678 values[staop_attnum] = ObjectIdGetDatum(staop);
679 replaces[staop_attnum] = true;
680 }
681 if (DatumGetObjectId(values[stacoll_attnum]) != stacoll)
682 {
683 values[stacoll_attnum] = ObjectIdGetDatum(stacoll);
684 replaces[stacoll_attnum] = true;
685 }
686 if (!stanumbers_isnull)
687 {
688 values[Anum_pg_statistic_stanumbers1 - 1 + slotidx] = stanumbers;
689 nulls[Anum_pg_statistic_stanumbers1 - 1 + slotidx] = false;
690 replaces[Anum_pg_statistic_stanumbers1 - 1 + slotidx] = true;
691 }
692 if (!stavalues_isnull)
693 {
694 values[Anum_pg_statistic_stavalues1 - 1 + slotidx] = stavalues;
695 nulls[Anum_pg_statistic_stavalues1 - 1 + slotidx] = false;
696 replaces[Anum_pg_statistic_stavalues1 - 1 + slotidx] = true;
int16 AttrNumber
Definition: attnum.h:21
static Oid DatumGetObjectId(Datum X)
Definition: postgres.h:252
static int16 DatumGetInt16(Datum X)
Definition: postgres.h:172

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

Referenced by attribute_statistics_update().

◆ stats_check_arg_array()

bool stats_check_arg_array ( FunctionCallInfo  fcinfo,
struct StatsArgInfo arginfo,
int  argnum 
)

Definition at line 69 of file stat_utils.c.

74{
75 ArrayType *arr;
76
77 if (PG_ARGISNULL(argnum))
78 return true;
79
81
82 if (ARR_NDIM(arr) != 1)
83 {
85 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
86 errmsg("argument \"%s\" must not be a multidimensional array",
87 arginfo[argnum].argname)));
88 return false;
89 }
90
91 if (array_contains_nulls(arr))
92 {
94 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
95 errmsg("argument \"%s\" array must not contain null values",
96 arginfo[argnum].argname)));
97 return false;
98 }
99
#define ARR_NDIM(a)
Definition: array.h:290
#define PG_ARGISNULL(n)
Definition: fmgr.h:209
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:268

References ARR_NDIM, array_contains_nulls(), DatumGetArrayTypeP, ereport, errcode(), errmsg(), PG_ARGISNULL, PG_GETARG_DATUM, and WARNING.

Referenced by attribute_statistics_update().

◆ stats_check_arg_pair()

bool stats_check_arg_pair ( FunctionCallInfo  fcinfo,
struct StatsArgInfo arginfo,
int  argnum1,
int  argnum2 
)

Definition at line 110 of file stat_utils.c.

115{
116 if (PG_ARGISNULL(argnum1) && PG_ARGISNULL(argnum2))
117 return true;
118
119 if (PG_ARGISNULL(argnum1) || PG_ARGISNULL(argnum2))
120 {
121 int nullarg = PG_ARGISNULL(argnum1) ? argnum1 : argnum2;
122 int otherarg = PG_ARGISNULL(argnum1) ? argnum2 : argnum1;
123
125 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
126 errmsg("argument \"%s\" must be specified when argument \"%s\" is specified",
127 arginfo[nullarg].argname,
128 arginfo[otherarg].argname)));
129
130 return false;
131 }
132

References ereport, errcode(), errmsg(), PG_ARGISNULL, and WARNING.

Referenced by attribute_statistics_update().

◆ stats_check_arg_type()

static bool stats_check_arg_type ( const char *  argname,
Oid  argtype,
Oid  expectedtype 
)
static

Definition at line 279 of file stat_utils.c.

282{
283 if (argtype != expectedtype)
284 {
286 (errmsg("argument \"%s\" has type %s, expected type %s",
287 argname, format_type_be(argtype),
288 format_type_be(expectedtype))));
289 return false;
290 }
291
char * format_type_be(Oid type_oid)
Definition: format_type.c:343

References ereport, errmsg(), format_type_be(), and WARNING.

Referenced by stats_fill_fcinfo_from_arg_pairs().

◆ stats_check_required_arg()

void stats_check_required_arg ( FunctionCallInfo  fcinfo,
struct StatsArgInfo arginfo,
int  argnum 
)

Definition at line 50 of file stat_utils.c.

55{
56 if (PG_ARGISNULL(argnum))
58 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
59 errmsg("argument \"%s\" must not be null",

References ereport, errcode(), errmsg(), ERROR, and PG_ARGISNULL.

Referenced by attribute_statistics_update(), pg_clear_attribute_stats(), and relation_statistics_update().

◆ stats_fill_fcinfo_from_arg_pairs()

bool stats_fill_fcinfo_from_arg_pairs ( FunctionCallInfo  pairs_fcinfo,
FunctionCallInfo  positional_fcinfo,
struct StatsArgInfo arginfo 
)

Definition at line 347 of file stat_utils.c.

352{
353 Datum *args;
354 bool *argnulls;
355 Oid *types;
356 int nargs;
357 bool result = true;
358
359 /* clear positional args */
360 for (int i = 0; arginfo[i].argname != NULL; i++)
361 {
362 positional_fcinfo->args[i].value = (Datum) 0;
363 positional_fcinfo->args[i].isnull = true;
364 }
365
366 nargs = extract_variadic_args(pairs_fcinfo, 0, true,
367 &args, &types, &argnulls);
368
369 if (nargs % 2 != 0)
371 errmsg("variadic arguments must be name/value pairs"),
372 errhint("Provide an even number of variadic arguments that can be divided into pairs."));
373
374 /*
375 * For each argument name/value pair, find corresponding positional
376 * argument for the argument name, and assign the argument value to
377 * positional_fcinfo.
378 */
379 for (int i = 0; i < nargs; i += 2)
380 {
381 int argnum;
382 char *argname;
383
384 if (argnulls[i])
386 (errmsg("name at variadic position %d is null", i + 1)));
387
388 if (types[i] != TEXTOID)
390 (errmsg("name at variadic position %d has type %s, expected type %s",
391 i + 1, format_type_be(types[i]),
392 format_type_be(TEXTOID))));
393
394 if (argnulls[i + 1])
395 continue;
396
397 argname = TextDatumGetCString(args[i]);
398
399 /*
400 * The 'version' argument is a special case, not handled by arginfo
401 * because it's not a valid positional argument.
402 *
403 * For now, 'version' is accepted but ignored. In the future it can be
404 * used to interpret older statistics properly.
405 */
406 if (pg_strcasecmp(argname, "version") == 0)
407 continue;
408
409 argnum = get_arg_by_name(argname, arginfo);
410
411 if (argnum < 0 || !stats_check_arg_type(argname, types[i + 1],
412 arginfo[argnum].argtype))
413 {
414 result = false;
415 continue;
416 }
417
418 positional_fcinfo->args[argnum].value = args[i + 1];
419 positional_fcinfo->args[argnum].isnull = false;
420 }
421
struct typedefs * types
Definition: ecpg.c:30
int errhint(const char *fmt,...)
Definition: elog.c:1330
int extract_variadic_args(FunctionCallInfo fcinfo, int variadic_start, bool convert_unknown, Datum **args, Oid **types, bool **nulls)
Definition: funcapi.c:2005
static int get_arg_by_name(const char *argname, struct StatsArgInfo *arginfo)
Definition: stat_utils.c:261
static bool stats_check_arg_type(const char *argname, Oid argtype, Oid expectedtype)
Definition: stat_utils.c:279
NullableDatum args[FLEXIBLE_ARRAY_MEMBER]
Definition: fmgr.h:95
Datum value
Definition: postgres.h:87
bool isnull
Definition: postgres.h:89

References StatsArgInfo::argname, generate_unaccent_rules::args, FunctionCallInfoBaseData::args, ereport, errhint(), errmsg(), ERROR, extract_variadic_args(), format_type_be(), get_arg_by_name(), i, NullableDatum::isnull, pg_strcasecmp(), stats_check_arg_type(), TextDatumGetCString, types, and NullableDatum::value.

Referenced by pg_restore_attribute_stats(), and pg_restore_relation_stats().