PostgreSQL Source Code git master
Loading...
Searching...
No Matches
stat_utils.h File Reference
#include "access/attnum.h"
#include "fmgr.h"
Include dependency graph for stat_utils.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  StatsArgInfo
 

Typedefs

typedef struct RangeVar RangeVar
 

Functions

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)
 
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)
 
void statatt_init_empty_tuple (Oid reloid, int16 attnum, bool inherited, Datum *values, bool *nulls, bool *replaces)
 
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)
 
Datum statatt_build_stavalues (const char *staname, FmgrInfo *array_in, Datum d, Oid typid, int32 typmod, bool *ok)
 
bool statatt_get_elem_type (Oid atttypid, char atttyptype, Oid *elemtypid, Oid *elem_eq_opr)
 
bool statatt_check_bounds_histogram (Datum arrayval)
 

Typedef Documentation

◆ RangeVar

Definition at line 20 of file stat_utils.h.

Function Documentation

◆ RangeVarCallbackForStats()

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

Definition at line 143 of file stat_utils.c.

147{
148 Oid *locked_oid = (Oid *) arg;
149 Oid table_oid = relId;
150 HeapTuple tuple;
152 char relkind;
153
154 /*
155 * If we previously locked some other index's heap, and the name we're
156 * looking up no longer refers to that relation, release the now-useless
157 * lock.
158 */
159 if (relId != oldRelId && OidIsValid(*locked_oid))
160 {
163 }
164
165 /* If the relation does not exist, there's nothing more to do. */
166 if (!OidIsValid(relId))
167 return;
168
169 /* If the relation does exist, check whether it's an index. */
170 relkind = get_rel_relkind(relId);
171 if (relkind == RELKIND_INDEX ||
172 relkind == RELKIND_PARTITIONED_INDEX)
173 table_oid = IndexGetRelation(relId, false);
174
175 /*
176 * If retrying yields the same OID, there are a couple of extremely
177 * unlikely scenarios we need to handle.
178 */
179 if (relId == oldRelId)
180 {
181 /*
182 * If a previous lookup found an index, but the current lookup did
183 * not, the index was dropped and the OID was reused for something
184 * else between lookups. In theory, we could simply drop our lock on
185 * the index's parent table and proceed, but in the interest of
186 * avoiding complexity, we just error.
187 */
188 if (table_oid == relId && OidIsValid(*locked_oid))
191 errmsg("index \"%s\" was concurrently dropped",
192 relation->relname)));
193
194 /*
195 * If the current lookup found an index but a previous lookup either
196 * did not find an index or found one with a different parent
197 * relation, the relation was dropped and the OID was reused for an
198 * index between lookups. RangeVarGetRelidExtended() will have
199 * already locked the index at this point, so we can't just lock the
200 * newly discovered parent table OID without risking deadlock. As
201 * above, we just error in this case.
202 */
203 if (table_oid != relId && table_oid != *locked_oid)
206 errmsg("index \"%s\" was concurrently created",
207 relation->relname)));
208 }
209
211 if (!HeapTupleIsValid(tuple))
212 elog(ERROR, "cache lookup failed for OID %u", table_oid);
213 form = (Form_pg_class) GETSTRUCT(tuple);
214
215 /* the relkinds that can be used with ANALYZE */
216 switch (form->relkind)
217 {
218 case RELKIND_RELATION:
219 case RELKIND_MATVIEW:
222 break;
223 default:
226 errmsg("cannot modify statistics for relation \"%s\"",
227 NameStr(form->relname)),
229 }
230
231 if (form->relisshared)
234 errmsg("cannot modify statistics for shared relation")));
235
236 /* Check permissions */
238 {
240 GetUserId(),
242
243 if (aclresult != ACLCHECK_OK)
245 get_relkind_objtype(form->relkind),
246 NameStr(form->relname));
247 }
248
249 ReleaseSysCache(tuple);
250
251 /* Lock heap before index to avoid deadlock. */
252 if (relId != oldRelId && table_oid != relId)
253 {
AclResult
Definition acl.h:183
@ ACLCHECK_OK
Definition acl.h:184
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition aclchk.c:2672
bool object_ownercheck(Oid classid, Oid objectid, Oid roleid)
Definition aclchk.c:4156
AclResult pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode)
Definition aclchk.c:4105
#define NameStr(name)
Definition c.h:894
#define OidIsValid(objectId)
Definition c.h:917
Datum arg
Definition elog.c:1323
int errcode(int sqlerrcode)
Definition elog.c:875
#define ERROR
Definition elog.h:40
#define elog(elevel,...)
Definition elog.h:228
#define ereport(elevel,...)
Definition elog.h:152
Oid MyDatabaseId
Definition globals.c:96
#define HeapTupleIsValid(tuple)
Definition htup.h:78
static void * GETSTRUCT(const HeapTupleData *tuple)
Oid IndexGetRelation(Oid indexId, bool missing_ok)
Definition index.c:3616
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:2317
Oid GetUserId(void)
Definition miscinit.c:470
static char * errmsg
ObjectType get_relkind_objtype(char relkind)
#define ACL_MAINTAIN
Definition parsenodes.h:90
int errdetail_relkind_not_supported(char relkind)
Definition pg_class.c:24
FormData_pg_class * Form_pg_class
Definition pg_class.h:160
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:252
#define InvalidOid
unsigned int Oid
static int fb(int x)
char * relname
Definition primnodes.h:84
void ReleaseSysCache(HeapTuple tuple)
Definition syscache.c:265
HeapTuple SearchSysCache1(SysCacheIdentifier cacheId, Datum key1)
Definition syscache.c:221

References ACL_MAINTAIN, aclcheck_error(), ACLCHECK_OK, arg, elog, ereport, errcode(), errdetail_relkind_not_supported(), errmsg, ERROR, fb(), 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(), extended_statistics_update(), pg_clear_attribute_stats(), pg_clear_extended_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 
)
extern

Definition at line 568 of file stat_utils.c.

572{
573 char *s;
576
577 escontext.details_wanted = true;
578
579 s = TextDatumGetCString(d);
580
581 if (!InputFunctionCallSafe(array_in, s, typid, typmod,
582 (Node *) &escontext, &result))
583 {
584 pfree(s);
585 escontext.error_data->elevel = WARNING;
586 ThrowErrorData(escontext.error_data);
587 *ok = false;
588 return (Datum) 0;
589 }
590
591 pfree(s);
592
594 {
597 errmsg("\"%s\" must be a one-dimensional array", staname)));
598 *ok = false;
599 return (Datum) 0;
600 }
601
603 {
606 errmsg("\"%s\" array must not contain null values", staname)));
607 *ok = false;
608 return (Datum) 0;
609 }
610
611 *ok = true;
612
#define ARR_NDIM(a)
Definition array.h:290
#define DatumGetArrayTypeP(X)
Definition array.h:261
bool array_contains_nulls(const ArrayType *array)
Datum array_in(PG_FUNCTION_ARGS)
Definition arrayfuncs.c:181
#define TextDatumGetCString(d)
Definition builtins.h:99
uint32 result
void ThrowErrorData(ErrorData *edata)
Definition elog.c:2091
#define WARNING
Definition elog.h:37
bool InputFunctionCallSafe(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod, Node *escontext, Datum *result)
Definition fmgr.c:1586
void pfree(void *pointer)
Definition mcxt.c:1619
uint64_t Datum
Definition postgres.h:70
Definition nodes.h:133

References ARR_NDIM, array_contains_nulls(), array_in(), DatumGetArrayTypeP, ErrorSaveContext::details_wanted, ErrorData::elevel, ereport, errcode(), errmsg, ErrorSaveContext::error_data, fb(), InputFunctionCallSafe(), pfree(), result, TextDatumGetCString, ThrowErrorData(), and WARNING.

Referenced by attribute_statistics_update_internal().

◆ statatt_check_bounds_histogram()

bool statatt_check_bounds_histogram ( Datum  arrayval)
extern

Definition at line 753 of file stat_utils.c.

756{
759 TypeCacheEntry *typcache;
760 int16 elmlen;
761 bool elmbyval;
762 char elmalign;
763 Datum *elems;
764 bool *nulls;
765 int nelems;
768
770
771 /*
772 * The element type should always be a range type here. This is
773 * defensive. If it isn't, the bounds histogram is never consulted by the
774 * range estimator, and there is nothing to verify.
775 */
776 if (typcache->rngelemtype == NULL)
777 return true;
778
779 get_typlenbyvalalign(rngtypid, &elmlen, &elmbyval, &elmalign);
780 deconstruct_array(arr, rngtypid, elmlen, elmbyval, elmalign,
781 &elems, &nulls, &nelems);
782
783 for (int i = 0; i < nelems; i++)
784 {
786 upper;
787 bool empty;
788
789 /*
790 * NULL elements are already rejected by statatt_build_stavalues() and
791 * array_in_safe().
792 */
793 range_deserialize(typcache, DatumGetRangeTypeP(elems[i]),
794 &lower, &upper, &empty);
795
796 if (empty)
797 {
800 errmsg("\"%s\" must not contain empty ranges",
801 "range_bounds_histogram")));
802 return false;
803 }
804
805 if (i > 0 &&
806 (range_cmp_bounds(typcache, &lower, &prev_lower) < 0 ||
807 range_cmp_bounds(typcache, &upper, &prev_upper) < 0))
808 {
811 errmsg("\"%s\" must have its lower and upper bounds sorted in ascending order",
812 "range_bounds_histogram")));
813 return false;
814 }
815
818 }
819
#define ARR_ELEMTYPE(a)
Definition array.h:292
void deconstruct_array(const ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
int16_t int16
Definition c.h:678
int i
Definition isn.c:77
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition lsyscache.c:2585
Datum lower(PG_FUNCTION_ARGS)
Datum upper(PG_FUNCTION_ARGS)
int range_cmp_bounds(TypeCacheEntry *typcache, const RangeBound *b1, const RangeBound *b2)
void range_deserialize(TypeCacheEntry *typcache, const RangeType *range, RangeBound *lower, RangeBound *upper, bool *empty)
static RangeType * DatumGetRangeTypeP(Datum X)
Definition rangetypes.h:73
struct TypeCacheEntry * rngelemtype
Definition typcache.h:99
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition typcache.c:389
#define TYPECACHE_RANGE_INFO
Definition typcache.h:149

References ARR_ELEMTYPE, DatumGetArrayTypeP, DatumGetRangeTypeP(), deconstruct_array(), ereport, errcode(), errmsg, fb(), get_typlenbyvalalign(), i, lookup_type_cache(), lower(), range_cmp_bounds(), range_deserialize(), TypeCacheEntry::rngelemtype, TYPECACHE_RANGE_INFO, upper(), and WARNING.

Referenced by attribute_statistics_update_internal(), and import_pg_statistic().

◆ statatt_get_elem_type()

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

Definition at line 524 of file stat_utils.c.

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

References fb(), get_base_element_type(), lookup_type_cache(), OidIsValid, and TYPECACHE_EQ_OPR.

Referenced by attribute_statistics_update_internal(), and import_pg_statistic().

◆ 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 
)
extern

Definition at line 438 of file stat_utils.c.

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

References AccessShareLock, attnum, TypeCacheEntry::eq_opr, ereport, errcode(), errmsg, ERROR, exprCollation(), exprType(), exprTypmod(), fb(), 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_internal().

◆ statatt_init_empty_tuple()

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

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 */
722 nulls[Anum_pg_statistic_starelid - 1] = false;
724 nulls[Anum_pg_statistic_staattnum - 1] = false;
726 nulls[Anum_pg_statistic_stainherit - 1] = false;
727
729 nulls[Anum_pg_statistic_stanullfrac - 1] = false;
731 nulls[Anum_pg_statistic_stawidth - 1] = false;
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 {
739 nulls[Anum_pg_statistic_stakind1 + slotnum - 1] = false;
741 nulls[Anum_pg_statistic_staop1 + slotnum - 1] = false;
743 nulls[Anum_pg_statistic_stacoll1 + slotnum - 1] = false;
static Datum values[MAXATTR]
Definition bootstrap.c:190
#define STATISTIC_NUM_SLOTS
static Datum BoolGetDatum(bool X)
Definition postgres.h:112
#define DEFAULT_STATATT_NULL_FRAC
Definition stat_utils.c:42
#define DEFAULT_STATATT_AVG_WIDTH
Definition stat_utils.c:43
#define DEFAULT_STATATT_N_DISTINCT
Definition stat_utils.c:44

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

Referenced by attribute_statistics_update_internal(), and import_pg_statistic().

◆ 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 
)
extern

Definition at line 634 of file stat_utils.c.

640{
641 int slotidx;
642 int first_empty = -1;
646
647 /* find existing slot with given stakind */
649 {
651
652 if (first_empty < 0 &&
655 if (DatumGetInt16(values[stakind_attnum]) == stakind)
656 break;
657 }
658
661
664 (errmsg("maximum number of statistics slots exceeded: %d",
665 slotidx + 1)));
666
670
671 if (DatumGetInt16(values[stakind_attnum]) != stakind)
672 {
674 replaces[stakind_attnum] = true;
675 }
676 if (DatumGetObjectId(values[staop_attnum]) != staop)
677 {
679 replaces[staop_attnum] = true;
680 }
681 if (DatumGetObjectId(values[stacoll_attnum]) != stacoll)
682 {
684 replaces[stacoll_attnum] = true;
685 }
687 {
688 values[Anum_pg_statistic_stanumbers1 - 1 + slotidx] = stanumbers;
689 nulls[Anum_pg_statistic_stanumbers1 - 1 + slotidx] = false;
691 }
692 if (!stavalues_isnull)
693 {
695 nulls[Anum_pg_statistic_stavalues1 - 1 + slotidx] = false;
int16 AttrNumber
Definition attnum.h:21
static Oid DatumGetObjectId(Datum X)
Definition postgres.h:242
static int16 DatumGetInt16(Datum X)
Definition postgres.h:162

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

Referenced by attribute_statistics_update_internal(), and import_pg_statistic().

◆ stats_check_arg_array()

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

Definition at line 71 of file stat_utils.c.

76{
77 ArrayType *arr;
78
80 return true;
81
83
84 if (ARR_NDIM(arr) != 1)
85 {
88 errmsg("argument \"%s\" must not be a multidimensional array",
89 arginfo[argnum].argname)));
90 return false;
91 }
92
93 if (array_contains_nulls(arr))
94 {
97 errmsg("argument \"%s\" array must not contain null values",
98 arginfo[argnum].argname)));
99 return false;
100 }
101
#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, fb(), PG_ARGISNULL, PG_GETARG_DATUM, and WARNING.

Referenced by attribute_statistics_update_internal().

◆ stats_check_arg_pair()

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

Definition at line 112 of file stat_utils.c.

117{
119 return true;
120
122 {
125
128 errmsg("argument \"%s\" must be specified when argument \"%s\" is specified",
129 arginfo[nullarg].argname,
130 arginfo[otherarg].argname)));
131
132 return false;
133 }
134

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

Referenced by attribute_statistics_update_internal().

◆ stats_check_required_arg()

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

◆ stats_fill_fcinfo_from_arg_pairs()

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

Definition at line 349 of file stat_utils.c.

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

References ereport, errhint(), errmsg, ERROR, extract_variadic_args(), fb(), format_type_be(), get_arg_by_name(), i, pg_strcasecmp(), result, stats_check_arg_type(), TextDatumGetCString, and types.

Referenced by pg_restore_attribute_stats(), pg_restore_extended_stats(), and pg_restore_relation_stats().