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)
 

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 142 of file stat_utils.c.

146{
147 Oid *locked_oid = (Oid *) arg;
148 Oid table_oid = relId;
149 HeapTuple tuple;
151 char relkind;
152
153 /*
154 * If we previously locked some other index's heap, and the name we're
155 * looking up no longer refers to that relation, release the now-useless
156 * lock.
157 */
158 if (relId != oldRelId && OidIsValid(*locked_oid))
159 {
162 }
163
164 /* If the relation does not exist, there's nothing more to do. */
165 if (!OidIsValid(relId))
166 return;
167
168 /* If the relation does exist, check whether it's an index. */
169 relkind = get_rel_relkind(relId);
170 if (relkind == RELKIND_INDEX ||
171 relkind == RELKIND_PARTITIONED_INDEX)
172 table_oid = IndexGetRelation(relId, false);
173
174 /*
175 * If retrying yields the same OID, there are a couple of extremely
176 * unlikely scenarios we need to handle.
177 */
178 if (relId == oldRelId)
179 {
180 /*
181 * If a previous lookup found an index, but the current lookup did
182 * not, the index was dropped and the OID was reused for something
183 * else between lookups. In theory, we could simply drop our lock on
184 * the index's parent table and proceed, but in the interest of
185 * avoiding complexity, we just error.
186 */
187 if (table_oid == relId && OidIsValid(*locked_oid))
190 errmsg("index \"%s\" was concurrently dropped",
191 relation->relname)));
192
193 /*
194 * If the current lookup found an index but a previous lookup either
195 * did not find an index or found one with a different parent
196 * relation, the relation was dropped and the OID was reused for an
197 * index between lookups. RangeVarGetRelidExtended() will have
198 * already locked the index at this point, so we can't just lock the
199 * newly discovered parent table OID without risking deadlock. As
200 * above, we just error in this case.
201 */
202 if (table_oid != relId && table_oid != *locked_oid)
205 errmsg("index \"%s\" was concurrently created",
206 relation->relname)));
207 }
208
210 if (!HeapTupleIsValid(tuple))
211 elog(ERROR, "cache lookup failed for OID %u", table_oid);
212 form = (Form_pg_class) GETSTRUCT(tuple);
213
214 /* the relkinds that can be used with ANALYZE */
215 switch (form->relkind)
216 {
217 case RELKIND_RELATION:
218 case RELKIND_MATVIEW:
221 break;
222 default:
225 errmsg("cannot modify statistics for relation \"%s\"",
226 NameStr(form->relname)),
228 }
229
230 if (form->relisshared)
233 errmsg("cannot modify statistics for shared relation")));
234
235 /* Check permissions */
237 {
239 GetUserId(),
241
242 if (aclresult != ACLCHECK_OK)
244 get_relkind_objtype(form->relkind),
245 NameStr(form->relname));
246 }
247
248 ReleaseSysCache(tuple);
249
250 /* Lock heap before index to avoid deadlock. */
251 if (relId != oldRelId && table_oid != relId)
252 {
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:765
#define OidIsValid(objectId)
Definition c.h:788
int errcode(int sqlerrcode)
Definition elog.c:863
int errmsg(const char *fmt,...)
Definition elog.c:1080
#define ERROR
Definition elog.h:39
#define elog(elevel,...)
Definition elog.h:226
#define ereport(elevel,...)
Definition elog.h:150
Oid MyDatabaseId
Definition globals.c:94
#define HeapTupleIsValid(tuple)
Definition htup.h:78
static void * GETSTRUCT(const HeapTupleData *tuple)
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
unsigned int Oid
static int fb(int x)
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, 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 567 of file stat_utils.c.

571{
572 LOCAL_FCINFO(fcinfo, 8);
573 char *s;
574 Datum result;
576
577 escontext.details_wanted = true;
578
579 s = TextDatumGetCString(d);
580
582 (Node *) &escontext, NULL);
583
584 fcinfo->args[0].value = CStringGetDatum(s);
585 fcinfo->args[0].isnull = false;
586 fcinfo->args[1].value = ObjectIdGetDatum(typid);
587 fcinfo->args[1].isnull = false;
588 fcinfo->args[2].value = Int32GetDatum(typmod);
589 fcinfo->args[2].isnull = false;
590
591 result = FunctionCallInvoke(fcinfo);
592
593 pfree(s);
594
595 if (escontext.error_occurred)
596 {
597 escontext.error_data->elevel = WARNING;
598 ThrowErrorData(escontext.error_data);
599 *ok = false;
600 return (Datum) 0;
601 }
602
604 {
607 errmsg("\"%s\" array must not contain null values", staname)));
608 *ok = false;
609 return (Datum) 0;
610 }
611
612 *ok = true;
613
#define DatumGetArrayTypeP(X)
Definition array.h:261
bool array_contains_nulls(const ArrayType *array)
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 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 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
static Datum Int32GetDatum(int32 X)
Definition postgres.h:222
int elevel
Definition elog.h:421
ErrorData * error_data
Definition miscnodes.h:49
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, fb(), 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 
)
extern

Definition at line 523 of file stat_utils.c.

527{
529
530 if (atttypid == TSVECTOROID)
531 {
532 /*
533 * Special case: element type for tsvector is text. See
534 * compute_tsvector_stats().
535 */
537 }
538 else
539 {
540 /* find underlying element type through any domain */
542 }
543
544 if (!OidIsValid(*elemtypid))
545 return false;
546
547 /* finds the right operator even if elemtypid is a domain */
549 if (!OidIsValid(elemtypcache->eq_opr))
550 return false;
551
552 *elem_eq_opr = elemtypcache->eq_opr;
553
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 fb(), get_base_element_type(), lookup_type_cache(), OidIsValid, and TYPECACHE_EQ_OPR.

Referenced by attribute_statistics_update().

◆ 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 437 of file stat_utils.c.

443{
447 Node *expr;
448 TypeCacheEntry *typcache;
449
452
453 /* Attribute not found */
457 errmsg("column %d of relation \"%s\" does not exist",
459
461
462 if (attr->attisdropped)
465 errmsg("column %d of relation \"%s\" does not exist",
467
468 expr = statatt_get_index_expr(rel, attr->attnum);
469
470 /*
471 * When analyzing an expression index, believe the expression tree's type
472 * not the column datatype --- the latter might be the opckeytype storage
473 * type of the opclass, which is not interesting for our purposes. This
474 * mimics the behavior of examine_attribute().
475 */
476 if (expr == NULL)
477 {
478 *atttypid = attr->atttypid;
479 *atttypmod = attr->atttypmod;
480 *atttypcoll = attr->attcollation;
481 }
482 else
483 {
484 *atttypid = exprType(expr);
485 *atttypmod = exprTypmod(expr);
486
487 if (OidIsValid(attr->attcollation))
488 *atttypcoll = attr->attcollation;
489 else
490 *atttypcoll = exprCollation(expr);
491 }
493
494 /*
495 * If it's a multirange, step down to the range type, as is done by
496 * multirange_typanalyze().
497 */
500
501 /* finds the right operators even if atttypid is a domain */
503 *atttyptype = typcache->typtype;
504 *eq_opr = typcache->eq_opr;
505 *lt_opr = typcache->lt_opr;
506
507 /*
508 * Special case: collation for tsvector is DEFAULT_COLLATION_OID. See
509 * compute_tsvector_stats().
510 */
511 if (*atttypid == TSVECTOROID)
513
#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
int16 attnum
FormData_pg_attribute * Form_pg_attribute
static Datum Int16GetDatum(int16 X)
Definition postgres.h:182
#define RelationGetRelationName(relation)
Definition rel.h:548
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:303
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(), 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().

◆ 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 713 of file stat_utils.c.

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

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().

◆ 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 635 of file stat_utils.c.

641{
642 int slotidx;
643 int first_empty = -1;
647
648 /* find existing slot with given stakind */
650 {
652
653 if (first_empty < 0 &&
656 if (DatumGetInt16(values[stakind_attnum]) == stakind)
657 break;
658 }
659
662
665 (errmsg("maximum number of statistics slots exceeded: %d",
666 slotidx + 1)));
667
671
672 if (DatumGetInt16(values[stakind_attnum]) != stakind)
673 {
675 replaces[stakind_attnum] = true;
676 }
677 if (DatumGetObjectId(values[staop_attnum]) != staop)
678 {
680 replaces[staop_attnum] = true;
681 }
682 if (DatumGetObjectId(values[stacoll_attnum]) != stacoll)
683 {
685 replaces[stacoll_attnum] = true;
686 }
688 {
689 values[Anum_pg_statistic_stanumbers1 - 1 + slotidx] = stanumbers;
690 nulls[Anum_pg_statistic_stanumbers1 - 1 + slotidx] = false;
692 }
693 if (!stavalues_isnull)
694 {
696 nulls[Anum_pg_statistic_stavalues1 - 1 + slotidx] = false;
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, fb(), 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 
)
extern

Definition at line 70 of file stat_utils.c.

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

Definition at line 111 of file stat_utils.c.

116{
118 return true;
119
121 {
124
127 errmsg("argument \"%s\" must be specified when argument \"%s\" is specified",
128 arginfo[nullarg].argname,
129 arginfo[otherarg].argname)));
130
131 return false;
132 }
133

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

Referenced by attribute_statistics_update().

◆ 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 348 of file stat_utils.c.

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

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

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