Here are a few patches related to attstattarget:- 0001: Change type of pg_statistic_ext.stxstattarget, to match attstattarget. Maybe this should go into PG16, for consistency?
- 0002: Add macro for maximum statistics target, instead of hardcoding it everywhere.
- 0003: Take pg_attribute out of VacAttrStats. This simplifies some code, especially for extended statistics, which had to have weird workarounds.
From f01d4c9aba44cc5b9028200b21a6d1df9770c5a2 Mon Sep 17 00:00:00 2001 From: Peter Eisentraut <pe...@eisentraut.org> Date: Tue, 27 Jun 2023 16:38:00 +0200 Subject: [PATCH 1/3] Change type of pg_statistic_ext.stxstattarget Change from int32 to int16, to match attstattarget (changed in 90189eefc1). --- doc/src/sgml/catalogs.sgml | 2 +- src/backend/commands/statscmds.c | 4 ++-- src/include/catalog/pg_statistic_ext.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml index ed32ca0349..852cb30ae1 100644 --- a/doc/src/sgml/catalogs.sgml +++ b/doc/src/sgml/catalogs.sgml @@ -7622,7 +7622,7 @@ <title><structname>pg_statistic_ext</structname> Columns</title> <row> <entry role="catalog_table_entry"><para role="column_definition"> - <structfield>stxstattarget</structfield> <type>int4</type> + <structfield>stxstattarget</structfield> <type>int2</type> </para> <para> <structfield>stxstattarget</structfield> controls the level of detail diff --git a/src/backend/commands/statscmds.c b/src/backend/commands/statscmds.c index 26ebd0819d..c2dab20bdc 100644 --- a/src/backend/commands/statscmds.c +++ b/src/backend/commands/statscmds.c @@ -498,7 +498,7 @@ CreateStatistics(CreateStatsStmt *stmt) values[Anum_pg_statistic_ext_stxrelid - 1] = ObjectIdGetDatum(relid); values[Anum_pg_statistic_ext_stxname - 1] = NameGetDatum(&stxname); values[Anum_pg_statistic_ext_stxnamespace - 1] = ObjectIdGetDatum(namespaceId); - values[Anum_pg_statistic_ext_stxstattarget - 1] = Int32GetDatum(-1); + values[Anum_pg_statistic_ext_stxstattarget - 1] = Int16GetDatum(-1); values[Anum_pg_statistic_ext_stxowner - 1] = ObjectIdGetDatum(stxowner); values[Anum_pg_statistic_ext_stxkeys - 1] = PointerGetDatum(stxkeys); values[Anum_pg_statistic_ext_stxkind - 1] = PointerGetDatum(stxkind); @@ -676,7 +676,7 @@ AlterStatistics(AlterStatsStmt *stmt) /* replace the stxstattarget column */ repl_repl[Anum_pg_statistic_ext_stxstattarget - 1] = true; - repl_val[Anum_pg_statistic_ext_stxstattarget - 1] = Int32GetDatum(newtarget); + repl_val[Anum_pg_statistic_ext_stxstattarget - 1] = Int16GetDatum(newtarget); newtup = heap_modify_tuple(oldtup, RelationGetDescr(rel), repl_val, repl_null, repl_repl); diff --git a/src/include/catalog/pg_statistic_ext.h b/src/include/catalog/pg_statistic_ext.h index 53eec9025a..1e64aa8f16 100644 --- a/src/include/catalog/pg_statistic_ext.h +++ b/src/include/catalog/pg_statistic_ext.h @@ -43,7 +43,7 @@ CATALOG(pg_statistic_ext,3381,StatisticExtRelationId) * object's namespace */ Oid stxowner BKI_LOOKUP(pg_authid); /* statistics object's owner */ - int32 stxstattarget BKI_DEFAULT(-1); /* statistics target */ + int16 stxstattarget BKI_DEFAULT(-1); /* statistics target */ /* * variable-length fields start here, but we allow direct access to -- 2.41.0
From a473c258577f9f9b28435feef27e8cbc25721d5c Mon Sep 17 00:00:00 2001 From: Peter Eisentraut <pe...@eisentraut.org> Date: Tue, 27 Jun 2023 14:09:39 +0200 Subject: [PATCH 2/3] Add macro for maximum statistics target The number of places where 10000 was hardcoded had grown a bit beyond the comfort level. Introduce a macro MAX_STATISTICS_TARGET instead. --- src/backend/commands/statscmds.c | 4 ++-- src/backend/commands/tablecmds.c | 5 +++-- src/backend/statistics/extended_stats.c | 2 +- src/backend/utils/misc/guc_tables.c | 2 +- src/include/catalog/pg_attribute.h | 2 +- src/include/commands/vacuum.h | 7 +++++++ src/include/statistics/statistics.h | 4 ++-- 7 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/backend/commands/statscmds.c b/src/backend/commands/statscmds.c index c2dab20bdc..36bc8c33ba 100644 --- a/src/backend/commands/statscmds.c +++ b/src/backend/commands/statscmds.c @@ -619,9 +619,9 @@ AlterStatistics(AlterStatsStmt *stmt) errmsg("statistics target %d is too low", newtarget))); } - else if (newtarget > 10000) + else if (newtarget > MAX_STATISTICS_TARGET) { - newtarget = 10000; + newtarget = MAX_STATISTICS_TARGET; ereport(WARNING, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("lowering statistics target to %d", diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index d985278ac6..fce5e6f220 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -61,6 +61,7 @@ #include "commands/trigger.h" #include "commands/typecmds.h" #include "commands/user.h" +#include "commands/vacuum.h" #include "executor/executor.h" #include "foreign/fdwapi.h" #include "foreign/foreign.h" @@ -8180,9 +8181,9 @@ ATExecSetStatistics(Relation rel, const char *colName, int16 colNum, Node *newVa errmsg("statistics target %d is too low", newtarget))); } - else if (newtarget > 10000) + else if (newtarget > MAX_STATISTICS_TARGET) { - newtarget = 10000; + newtarget = MAX_STATISTICS_TARGET; ereport(WARNING, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("lowering statistics target to %d", diff --git a/src/backend/statistics/extended_stats.c b/src/backend/statistics/extended_stats.c index 28b52d8aa1..513ddf540a 100644 --- a/src/backend/statistics/extended_stats.c +++ b/src/backend/statistics/extended_stats.c @@ -379,7 +379,7 @@ statext_compute_stattarget(int stattarget, int nattrs, VacAttrStats **stats) stattarget = default_statistics_target; /* As this point we should have a valid statistics target. */ - Assert((stattarget >= 0) && (stattarget <= 10000)); + Assert((stattarget >= 0) && (stattarget <= MAX_STATISTICS_TARGET)); return stattarget; } diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c index 71e27f8eb0..f8ef87d26d 100644 --- a/src/backend/utils/misc/guc_tables.c +++ b/src/backend/utils/misc/guc_tables.c @@ -2035,7 +2035,7 @@ struct config_int ConfigureNamesInt[] = "column-specific target set via ALTER TABLE SET STATISTICS.") }, &default_statistics_target, - 100, 1, 10000, + 100, 1, MAX_STATISTICS_TARGET, NULL, NULL, NULL }, { diff --git a/src/include/catalog/pg_attribute.h b/src/include/catalog/pg_attribute.h index f8b4861b94..f00df488ce 100644 --- a/src/include/catalog/pg_attribute.h +++ b/src/include/catalog/pg_attribute.h @@ -165,7 +165,7 @@ CATALOG(pg_attribute,1249,AttributeRelationId) BKI_BOOTSTRAP BKI_ROWTYPE_OID(75, * that no value has been explicitly set for this column, so ANALYZE * should use the default setting. * - * int16 is sufficient because the max value is currently 10000. + * int16 is sufficient for the current max value (MAX_STATISTICS_TARGET). */ int16 attstattarget BKI_DEFAULT(-1); diff --git a/src/include/commands/vacuum.h b/src/include/commands/vacuum.h index cb5b11ab31..bda7792770 100644 --- a/src/include/commands/vacuum.h +++ b/src/include/commands/vacuum.h @@ -305,6 +305,13 @@ extern PGDLLIMPORT int vacuum_multixact_freeze_table_age; extern PGDLLIMPORT int vacuum_failsafe_age; extern PGDLLIMPORT int vacuum_multixact_failsafe_age; +/* + * Maximum value for default_statistics_target and per-column statistics + * targets. This is fairly arbitrary, mainly to prevent users from creating + * unreasonably large statistics that the system cannot handle well. + */ +#define MAX_STATISTICS_TARGET 10000 + /* Variables for cost-based parallel vacuum */ extern PGDLLIMPORT pg_atomic_uint32 *VacuumSharedCostBalance; extern PGDLLIMPORT pg_atomic_uint32 *VacuumActiveNWorkers; diff --git a/src/include/statistics/statistics.h b/src/include/statistics/statistics.h index 17e3e7f881..5e538fec32 100644 --- a/src/include/statistics/statistics.h +++ b/src/include/statistics/statistics.h @@ -66,8 +66,8 @@ typedef struct MVDependencies #define STATS_MCV_MAGIC 0xE1A651C2 /* marks serialized bytea */ #define STATS_MCV_TYPE_BASIC 1 /* basic MCV list type */ -/* max items in MCV list (should be equal to max default_statistics_target) */ -#define STATS_MCVLIST_MAX_ITEMS 10000 +/* max items in MCV list */ +#define STATS_MCVLIST_MAX_ITEMS MAX_STATISTICS_TARGET /* * Multivariate MCV (most-common value) lists -- 2.41.0
From d01f498ac24f2f8116357776b585fc401536df35 Mon Sep 17 00:00:00 2001 From: Peter Eisentraut <pe...@eisentraut.org> Date: Tue, 27 Jun 2023 16:29:13 +0200 Subject: [PATCH 3/3] Take pg_attribute out of VacAttrStats The VacAttrStats structure contained the whole Form_pg_attribute for a column, but it actually only needs attstattarget from there. So remove the Form_pg_attribute field and make a separate field for attstattarget. This simplifies some code for extended statistics that doesn't deal with a column but an expression, which had to fake up pg_attribute rows to satisfy internal APIs. Also, we can remove some comments that essentially said "don't look at pg_attribute directly". --- src/backend/commands/analyze.c | 33 ++++++------- src/backend/statistics/extended_stats.c | 48 +++++-------------- src/backend/tsearch/ts_typanalyze.c | 10 ++-- src/backend/utils/adt/array_typanalyze.c | 4 +- src/backend/utils/adt/rangetypes_typanalyze.c | 16 +++---- src/include/commands/vacuum.h | 12 ++--- 6 files changed, 43 insertions(+), 80 deletions(-) diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c index fc9a371f9b..9c8413eef2 100644 --- a/src/backend/commands/analyze.c +++ b/src/backend/commands/analyze.c @@ -572,7 +572,7 @@ do_analyze_rel(Relation onerel, VacuumParams *params, * If the appropriate flavor of the n_distinct option is * specified, override with the corresponding value. */ - aopt = get_attribute_options(onerel->rd_id, stats->attr->attnum); + aopt = get_attribute_options(onerel->rd_id, stats->tupattnum); if (aopt != NULL) { float8 n_distinct; @@ -927,7 +927,7 @@ compute_index_stats(Relation onerel, double totalrows, for (i = 0; i < attr_cnt; i++) { VacAttrStats *stats = thisdata->vacattrstats[i]; - int attnum = stats->attr->attnum; + int attnum = stats->tupattnum; if (isnull[attnum - 1]) { @@ -1014,12 +1014,10 @@ examine_attribute(Relation onerel, int attnum, Node *index_expr) return NULL; /* - * Create the VacAttrStats struct. Note that we only have a copy of the - * fixed fields of the pg_attribute tuple. + * Create the VacAttrStats struct. */ stats = (VacAttrStats *) palloc0(sizeof(VacAttrStats)); - stats->attr = (Form_pg_attribute) palloc(ATTRIBUTE_FIXED_PART_SIZE); - memcpy(stats->attr, attr, ATTRIBUTE_FIXED_PART_SIZE); + stats->attstattarget = attr->attstattarget; /* * When analyzing an expression index, believe the expression tree's type @@ -1086,7 +1084,6 @@ examine_attribute(Relation onerel, int attnum, Node *index_expr) if (!ok || stats->compute_stats == NULL || stats->minrows <= 0) { heap_freetuple(typtuple); - pfree(stats->attr); pfree(stats); return NULL; } @@ -1659,7 +1656,7 @@ update_attstats(Oid relid, bool inh, int natts, VacAttrStats **vacattrstats) } values[Anum_pg_statistic_starelid - 1] = ObjectIdGetDatum(relid); - values[Anum_pg_statistic_staattnum - 1] = Int16GetDatum(stats->attr->attnum); + values[Anum_pg_statistic_staattnum - 1] = Int16GetDatum(stats->tupattnum); values[Anum_pg_statistic_stainherit - 1] = BoolGetDatum(inh); values[Anum_pg_statistic_stanullfrac - 1] = Float4GetDatum(stats->stanullfrac); values[Anum_pg_statistic_stawidth - 1] = Int32GetDatum(stats->stawidth); @@ -1725,7 +1722,7 @@ update_attstats(Oid relid, bool inh, int natts, VacAttrStats **vacattrstats) /* Is there already a pg_statistic tuple for this attribute? */ oldtup = SearchSysCache3(STATRELATTINH, ObjectIdGetDatum(relid), - Int16GetDatum(stats->attr->attnum), + Int16GetDatum(stats->tupattnum), BoolGetDatum(inh)); /* Open index information when we know we need it */ @@ -1860,15 +1857,13 @@ static int analyze_mcv_list(int *mcv_counts, bool std_typanalyze(VacAttrStats *stats) { - Form_pg_attribute attr = stats->attr; Oid ltopr; Oid eqopr; StdAnalyzeData *mystats; /* If the attstattarget column is negative, use the default value */ - /* NB: it is okay to scribble on stats->attr since it's a copy */ - if (attr->attstattarget < 0) - attr->attstattarget = default_statistics_target; + if (stats->attstattarget < 0) + stats->attstattarget = default_statistics_target; /* Look for default "<" and "=" operators for column's type */ get_sort_group_operators(stats->attrtypid, @@ -1909,21 +1904,21 @@ std_typanalyze(VacAttrStats *stats) * know it at this point. *-------------------- */ - stats->minrows = 300 * attr->attstattarget; + stats->minrows = 300 * stats->attstattarget; } else if (OidIsValid(eqopr)) { /* We can still recognize distinct values */ stats->compute_stats = compute_distinct_stats; /* Might as well use the same minrows as above */ - stats->minrows = 300 * attr->attstattarget; + stats->minrows = 300 * stats->attstattarget; } else { /* Can't do much but the trivial stuff */ stats->compute_stats = compute_trivial_stats; /* Might as well use the same minrows as above */ - stats->minrows = 300 * attr->attstattarget; + stats->minrows = 300 * stats->attstattarget; } return true; @@ -2051,7 +2046,7 @@ compute_distinct_stats(VacAttrStatsP stats, TrackItem *track; int track_cnt, track_max; - int num_mcv = stats->attr->attstattarget; + int num_mcv = stats->attstattarget; StdAnalyzeData *mystats = (StdAnalyzeData *) stats->extra_data; /* @@ -2392,8 +2387,8 @@ compute_scalar_stats(VacAttrStatsP stats, int *tupnoLink; ScalarMCVItem *track; int track_cnt = 0; - int num_mcv = stats->attr->attstattarget; - int num_bins = stats->attr->attstattarget; + int num_mcv = stats->attstattarget; + int num_bins = stats->attstattarget; StdAnalyzeData *mystats = (StdAnalyzeData *) stats->extra_data; values = (ScalarItem *) palloc(samplerows * sizeof(ScalarItem)); diff --git a/src/backend/statistics/extended_stats.c b/src/backend/statistics/extended_stats.c index 513ddf540a..9f67a57724 100644 --- a/src/backend/statistics/extended_stats.c +++ b/src/backend/statistics/extended_stats.c @@ -366,8 +366,8 @@ statext_compute_stattarget(int stattarget, int nattrs, VacAttrStats **stats) for (i = 0; i < nattrs; i++) { /* keep the maximum statistics target */ - if (stats[i]->attr->attstattarget > stattarget) - stattarget = stats[i]->attr->attstattarget; + if (stats[i]->attstattarget > stattarget) + stattarget = stats[i]->attstattarget; } /* @@ -534,14 +534,10 @@ examine_attribute(Node *expr) bool ok; /* - * Create the VacAttrStats struct. Note that we only have a copy of the - * fixed fields of the pg_attribute tuple. + * Create the VacAttrStats struct. */ stats = (VacAttrStats *) palloc0(sizeof(VacAttrStats)); - - /* fake the attribute */ - stats->attr = (Form_pg_attribute) palloc0(ATTRIBUTE_FIXED_PART_SIZE); - stats->attr->attstattarget = -1; + stats->attstattarget = -1; /* * When analyzing an expression, believe the expression tree's type not @@ -595,7 +591,6 @@ examine_attribute(Node *expr) if (!ok || stats->compute_stats == NULL || stats->minrows <= 0) { heap_freetuple(typtuple); - pfree(stats->attr); pfree(stats); return NULL; } @@ -624,6 +619,13 @@ examine_expression(Node *expr, int stattarget) */ stats = (VacAttrStats *) palloc0(sizeof(VacAttrStats)); + /* + * We can't have statistics target specified for the expression, so we + * could use either the default_statistics_target, or the target computed + * for the extended statistics. The second option seems more reasonable. + */ + stats->attstattarget = stattarget; + /* * When analyzing an expression, believe the expression tree's type. */ @@ -638,25 +640,6 @@ examine_expression(Node *expr, int stattarget) */ stats->attrcollid = exprCollation(expr); - /* - * We don't have any pg_attribute for expressions, so let's fake something - * reasonable into attstattarget, which is the only thing std_typanalyze - * needs. - */ - stats->attr = (Form_pg_attribute) palloc(ATTRIBUTE_FIXED_PART_SIZE); - - /* - * We can't have statistics target specified for the expression, so we - * could use either the default_statistics_target, or the target computed - * for the extended statistics. The second option seems more reasonable. - */ - stats->attr->attstattarget = stattarget; - - /* initialize some basic fields */ - stats->attr->attrelid = InvalidOid; - stats->attr->attnum = InvalidAttrNumber; - stats->attr->atttypid = stats->attrtypid; - typtuple = SearchSysCacheCopy1(TYPEOID, ObjectIdGetDatum(stats->attrtypid)); if (!HeapTupleIsValid(typtuple)) @@ -747,12 +730,6 @@ lookup_var_attr_stats(Relation rel, Bitmapset *attrs, List *exprs, return NULL; } - /* - * Sanity check that the column is not dropped - stats should have - * been removed in this case. - */ - Assert(!stats[i]->attr->attisdropped); - i++; } @@ -2237,8 +2214,7 @@ compute_expr_stats(Relation onerel, double totalrows, if (tcnt > 0) { AttributeOpts *aopt = - get_attribute_options(stats->attr->attrelid, - stats->attr->attnum); + get_attribute_options(onerel->rd_id, stats->tupattnum); stats->exprvals = exprvals; stats->exprnulls = exprnulls; diff --git a/src/backend/tsearch/ts_typanalyze.c b/src/backend/tsearch/ts_typanalyze.c index 75ecd72efe..6594322733 100644 --- a/src/backend/tsearch/ts_typanalyze.c +++ b/src/backend/tsearch/ts_typanalyze.c @@ -58,16 +58,14 @@ Datum ts_typanalyze(PG_FUNCTION_ARGS) { VacAttrStats *stats = (VacAttrStats *) PG_GETARG_POINTER(0); - Form_pg_attribute attr = stats->attr; /* If the attstattarget column is negative, use the default value */ - /* NB: it is okay to scribble on stats->attr since it's a copy */ - if (attr->attstattarget < 0) - attr->attstattarget = default_statistics_target; + if (stats->attstattarget < 0) + stats->attstattarget = default_statistics_target; stats->compute_stats = compute_tsvector_stats; /* see comment about the choice of minrows in commands/analyze.c */ - stats->minrows = 300 * attr->attstattarget; + stats->minrows = 300 * stats->attstattarget; PG_RETURN_BOOL(true); } @@ -169,7 +167,7 @@ compute_tsvector_stats(VacAttrStats *stats, * the number of individual lexeme values tracked in pg_statistic ought to * be more than the number of values for a simple scalar column. */ - num_mcelem = stats->attr->attstattarget * 10; + num_mcelem = stats->attstattarget * 10; /* * We set bucket width equal to (num_mcelem + 10) / 0.007 as per the diff --git a/src/backend/utils/adt/array_typanalyze.c b/src/backend/utils/adt/array_typanalyze.c index 52e160d6bb..04b3764b68 100644 --- a/src/backend/utils/adt/array_typanalyze.c +++ b/src/backend/utils/adt/array_typanalyze.c @@ -263,7 +263,7 @@ compute_array_stats(VacAttrStats *stats, AnalyzeAttrFetchFunc fetchfunc, * the number of individual elements tracked in pg_statistic ought to be * more than the number of values for a simple scalar column. */ - num_mcelem = stats->attr->attstattarget * 10; + num_mcelem = stats->attstattarget * 10; /* * We set bucket width equal to num_mcelem / 0.007 as per the comment @@ -575,7 +575,7 @@ compute_array_stats(VacAttrStats *stats, AnalyzeAttrFetchFunc fetchfunc, count_items_count = hash_get_num_entries(count_tab); if (count_items_count > 0) { - int num_hist = stats->attr->attstattarget; + int num_hist = stats->attstattarget; DECountItem **sorted_count_items; int j; int delta; diff --git a/src/backend/utils/adt/rangetypes_typanalyze.c b/src/backend/utils/adt/rangetypes_typanalyze.c index 86810a1a6e..d13d8d2c53 100644 --- a/src/backend/utils/adt/rangetypes_typanalyze.c +++ b/src/backend/utils/adt/rangetypes_typanalyze.c @@ -47,18 +47,17 @@ range_typanalyze(PG_FUNCTION_ARGS) { VacAttrStats *stats = (VacAttrStats *) PG_GETARG_POINTER(0); TypeCacheEntry *typcache; - Form_pg_attribute attr = stats->attr; /* Get information about range type; note column might be a domain */ typcache = range_get_typcache(fcinfo, getBaseType(stats->attrtypid)); - if (attr->attstattarget < 0) - attr->attstattarget = default_statistics_target; + if (stats->attstattarget < 0) + stats->attstattarget = default_statistics_target; stats->compute_stats = compute_range_stats; stats->extra_data = typcache; /* same as in std_typanalyze */ - stats->minrows = 300 * attr->attstattarget; + stats->minrows = 300 * stats->attstattarget; PG_RETURN_BOOL(true); } @@ -74,18 +73,17 @@ multirange_typanalyze(PG_FUNCTION_ARGS) { VacAttrStats *stats = (VacAttrStats *) PG_GETARG_POINTER(0); TypeCacheEntry *typcache; - Form_pg_attribute attr = stats->attr; /* Get information about multirange type; note column might be a domain */ typcache = multirange_get_typcache(fcinfo, getBaseType(stats->attrtypid)); - if (attr->attstattarget < 0) - attr->attstattarget = default_statistics_target; + if (stats->attstattarget < 0) + stats->attstattarget = default_statistics_target; stats->compute_stats = compute_range_stats; stats->extra_data = typcache; /* same as in std_typanalyze */ - stats->minrows = 300 * attr->attstattarget; + stats->minrows = 300 * stats->attstattarget; PG_RETURN_BOOL(true); } @@ -136,7 +134,7 @@ compute_range_stats(VacAttrStats *stats, AnalyzeAttrFetchFunc fetchfunc, int empty_cnt = 0; int range_no; int slot_idx; - int num_bins = stats->attr->attstattarget; + int num_bins = stats->attstattarget; int num_hist; float8 *lengths; RangeBound *lowers, diff --git a/src/include/commands/vacuum.h b/src/include/commands/vacuum.h index bda7792770..b027fb2c67 100644 --- a/src/include/commands/vacuum.h +++ b/src/include/commands/vacuum.h @@ -116,16 +116,12 @@ typedef struct VacAttrStats { /* * These fields are set up by the main ANALYZE code before invoking the - * type-specific typanalyze function. - * - * Note: do not assume that the data being analyzed has the same datatype - * shown in attr, ie do not trust attr->atttypid, attlen, etc. This is - * because some index opclasses store a different type than the underlying - * column/expression. Instead use attrtypid, attrtypmod, and attrtype for + * type-specific typanalyze function. They don't necessarily match what + * is in pg_attribute, because some index opclasses store a different type + * than the underlying column/expression. Therefore, use these fields for * information about the datatype being fed to the typanalyze function. - * Likewise, use attrcollid not attr->attcollation. */ - Form_pg_attribute attr; /* copy of pg_attribute row for column */ + int attstattarget; Oid attrtypid; /* type of data being analyzed */ int32 attrtypmod; /* typmod of data being analyzed */ Form_pg_type attrtype; /* copy of pg_type row for attrtypid */ -- 2.41.0