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". Reviewed-by: Tomas Vondra <tomas.vondra@enterprisedb.com> Discussion: https://www.postgresql.org/message-id/flat/d6069765-5971-04d3-c10d-e4f7b2e9c459%40eisentraut.org
This commit is contained in:
parent
7a7f60aef8
commit
c69bdf837f
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue