diff --git a/src/backend/commands/statscmds.c b/src/backend/commands/statscmds.c index cf406f6f96..34d11c2a98 100644 --- a/src/backend/commands/statscmds.c +++ b/src/backend/commands/statscmds.c @@ -485,6 +485,10 @@ RemoveStatisticsById(Oid statsOid) * * For MCV lists that's not the case, as those statistics store the datums * internally. In this case we simply reset the statistics value to NULL. + * + * Note that "type change" includes collation change, which means we can rely + * on the MCV list being consistent with the collation info in pg_attribute + * during estimation. */ void UpdateStatisticsForTypeChange(Oid statsOid, Oid relationOid, int attnum, diff --git a/src/backend/statistics/dependencies.c b/src/backend/statistics/dependencies.c index 66c38ce2bc..585cad2ad9 100644 --- a/src/backend/statistics/dependencies.c +++ b/src/backend/statistics/dependencies.c @@ -273,7 +273,7 @@ dependency_degree(int numrows, HeapTuple *rows, int k, AttrNumber *dependency, colstat->attrtypid); /* prepare the sort function for this dimension */ - multi_sort_add_dimension(mss, i, type->lt_opr, type->typcollation); + multi_sort_add_dimension(mss, i, type->lt_opr, colstat->attrcollid); } /* diff --git a/src/backend/statistics/mcv.c b/src/backend/statistics/mcv.c index 2b685ec67a..cec06f8c44 100644 --- a/src/backend/statistics/mcv.c +++ b/src/backend/statistics/mcv.c @@ -366,7 +366,7 @@ build_mss(VacAttrStats **stats, int numattrs) elog(ERROR, "cache lookup failed for ordering operator for type %u", colstat->attrtypid); - multi_sort_add_dimension(mss, i, type->lt_opr, type->typcollation); + multi_sort_add_dimension(mss, i, type->lt_opr, colstat->attrcollid); } return mss; @@ -686,7 +686,7 @@ statext_mcv_serialize(MCVList *mcvlist, VacAttrStats **stats) /* sort and deduplicate the data */ ssup[dim].ssup_cxt = CurrentMemoryContext; - ssup[dim].ssup_collation = DEFAULT_COLLATION_OID; + ssup[dim].ssup_collation = stats[dim]->attrcollid; ssup[dim].ssup_nulls_first = false; PrepareSortSupportFromOrderingOp(typentry->lt_opr, &ssup[dim]); @@ -1630,15 +1630,22 @@ mcv_get_match_bitmap(PlannerInfo *root, List *clauses, * First check whether the constant is below the lower * boundary (in that case we can skip the bucket, because * there's no overlap). + * + * We don't store collations used to build the statistics, + * but we can use the collation for the attribute itself, + * as stored in varcollid. We do reset the statistics after + * a type change (including collation change), so this is + * OK. We may need to relax this after allowing extended + * statistics on expressions. */ if (varonleft) match = DatumGetBool(FunctionCall2Coll(&opproc, - DEFAULT_COLLATION_OID, + var->varcollid, item->values[idx], cst->constvalue)); else match = DatumGetBool(FunctionCall2Coll(&opproc, - DEFAULT_COLLATION_OID, + var->varcollid, cst->constvalue, item->values[idx])); diff --git a/src/backend/statistics/mvdistinct.c b/src/backend/statistics/mvdistinct.c index 9ebf183d90..228fa2684f 100644 --- a/src/backend/statistics/mvdistinct.c +++ b/src/backend/statistics/mvdistinct.c @@ -477,7 +477,7 @@ ndistinct_for_combination(double totalrows, int numrows, HeapTuple *rows, colstat->attrtypid); /* prepare the sort function for this dimension */ - multi_sort_add_dimension(mss, i, type->lt_opr, type->typcollation); + multi_sort_add_dimension(mss, i, type->lt_opr, colstat->attrcollid); /* accumulate all the data for this dimension into the arrays */ for (j = 0; j < numrows; j++)