From f634478411b86bf89ae01f38b84d62ec3e0478be Mon Sep 17 00:00:00 2001 From: shihao zhong Date: Tue, 13 Oct 2026 00:44:21 -0400 Subject: [PATCH v2 1/3] Let pg_restore_extended_stats check the column names. n_distinct and dependencies refer to columns by number and the MCV list by position. Add an optional attnames argument with the column names of the source statistics object. If they do not match the target in the same order, skip these with a warning. --- doc/src/sgml/func/func-admin.sgml | 8 ++++ src/backend/statistics/extended_stats_funcs.c | 46 +++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/doc/src/sgml/func/func-admin.sgml b/doc/src/sgml/func/func-admin.sgml index 64b0e7bb972..935d4904c28 100644 --- a/doc/src/sgml/func/func-admin.sgml +++ b/doc/src/sgml/func/func-admin.sgml @@ -2274,6 +2274,14 @@ SELECT pg_restore_extended_stats( This is anticipated to be helpful in porting statistics from older versions of PostgreSQL. + + The argument attnames of type + text[] gives the names of the columns of the + statistics object the data was taken from. If they are not the + names of the columns of this statistics object, in the same order, + n_distinct, dependencies and + the most-common-values data are not restored. + Minor errors are reported as a WARNING and ignored, and remaining statistics will still be restored. If all diff --git a/src/backend/statistics/extended_stats_funcs.c b/src/backend/statistics/extended_stats_funcs.c index 00b8dbe3366..343e813c771 100644 --- a/src/backend/statistics/extended_stats_funcs.c +++ b/src/backend/statistics/extended_stats_funcs.c @@ -50,6 +50,7 @@ enum extended_stats_argnum STATSCHEMA_ARG, STATNAME_ARG, INHERITED_ARG, + ATTNAMES_ARG, NDISTINCT_ARG, DEPENDENCIES_ARG, MOST_COMMON_VALS_ARG, @@ -70,6 +71,7 @@ static struct StatsArgInfo extarginfo[] = [STATSCHEMA_ARG] = {"statistics_schemaname", TEXTOID}, [STATNAME_ARG] = {"statistics_name", TEXTOID}, [INHERITED_ARG] = {"inherited", BOOLOID}, + [ATTNAMES_ARG] = {"attnames", TEXTARRAYOID}, [NDISTINCT_ARG] = {"n_distinct", PG_NDISTINCTOID}, [DEPENDENCIES_ARG] = {"dependencies", PG_DEPENDENCIESOID}, [MOST_COMMON_VALS_ARG] = {"most_common_vals", TEXTARRAYOID}, @@ -569,6 +571,50 @@ extended_statistics_update(FunctionCallInfo fcinfo) success = false; } + /* + * If the caller gave the column names of the statistics object the data + * was taken from, they must be the names of our columns, in the same + * order. n_distinct and dependencies refer to columns by number and the + * MCV list by position, so none of them can be used otherwise. + */ + if (!PG_ARGISNULL(ATTNAMES_ARG)) + { + ArrayType *arr = PG_GETARG_ARRAYTYPE_P(ATTNAMES_ARG); + bool match; + + match = ARR_NDIM(arr) <= 1 && !array_contains_nulls(arr) && + ArrayGetNItems(ARR_NDIM(arr), ARR_DIMS(arr)) == numattnums; + + if (match) + { + Datum *names; + int nnames; + + deconstruct_array_builtin(arr, TEXTOID, &names, NULL, &nnames); + for (int i = 0; i < numattnums && match; i++) + { + char *attname = get_attname(relid, + stxform->stxkeys.values[i], + false); + + match = strcmp(attname, TextDatumGetCString(names[i])) == 0; + } + } + + if (!match) + { + ereport(WARNING, + errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("could not restore extended statistics object \"%s.%s\": its columns do not match \"%s\"", + nspname, stxname, + extarginfo[ATTNAMES_ARG].argname)); + has.ndistinct = false; + has.dependencies = false; + has.mcv = false; + success = false; + } + } + /* * Either of these statistic types requires that we supply a semi-filled * VacAttrStatsP array. -- 2.37.1 (Apple Git-137.1)