From a1433a72b43430b86b9209c134dcfb9cf0d6ec9b Mon Sep 17 00:00:00 2001 From: Michael Paquier Date: Tue, 1 Sep 2026 17:07:05 +0900 Subject: [PATCH v2 2/2] Use named structs for the statistics values to import This simplifies the interface of postgres_fdw for the import of the stats, removing the need of a round-trip in terms of a NullableDatum array built on the FDW side before rebuilding it in the stats update path. The stats import functions also become deeply simplified, passing down one pointer to a structure with all the values assigned. Author: Michael Paquier --- src/include/statistics/stat_utils.h | 11 +- src/include/statistics/statistics.h | 66 ++++++--- src/backend/statistics/attribute_stats.c | 162 ++++++++++------------- src/backend/statistics/relation_stats.c | 64 ++++----- src/backend/statistics/stat_utils.c | 28 ++-- contrib/postgres_fdw/postgres_fdw.c | 69 +++++----- src/tools/pgindent/typedefs.list | 2 + 7 files changed, 197 insertions(+), 205 deletions(-) diff --git a/src/include/statistics/stat_utils.h b/src/include/statistics/stat_utils.h index 0560826fcfe5..8544c064bbb1 100644 --- a/src/include/statistics/stat_utils.h +++ b/src/include/statistics/stat_utils.h @@ -28,11 +28,12 @@ struct StatsArgInfo extern void stats_check_required_arg(const NullableDatum *args, struct StatsArgInfo *arginfo, int argnum); -extern bool stats_check_arg_array(const NullableDatum *args, - struct StatsArgInfo *arginfo, int argnum); -extern bool stats_check_arg_pair(const NullableDatum *args, - struct StatsArgInfo *arginfo, - int argnum1, int argnum2); +extern bool stats_check_arg_array(const NullableDatum *arg, + const char *argname); +extern bool stats_check_arg_pair(const NullableDatum *arg1, + const NullableDatum *arg2, + const char *argname1, + const char *argname2); extern void RangeVarCallbackForStats(const RangeVar *relation, Oid relId, Oid oldRelId, void *arg); diff --git a/src/include/statistics/statistics.h b/src/include/statistics/statistics.h index 0b163103a729..fa0430b94774 100644 --- a/src/include/statistics/statistics.h +++ b/src/include/statistics/statistics.h @@ -128,28 +128,56 @@ extern StatisticExtInfo *choose_best_statistics(List *stats, char requiredkind, int nclauses); extern HeapTuple statext_expressions_load(Oid stxoid, bool inh, int idx); +/* + * Statistics values applied to pg_class during stats import or restore + * + * A field with isnull set to true leaves the corresponding pg_class column + * untouched. The caller must initialize every field. + * + * The "version" field is currently ignored. In the future it can be used to + * interpret the format of older statistics. + */ +typedef struct RelationStatsValues +{ + NullableDatum version; + NullableDatum relpages; + NullableDatum reltuples; + NullableDatum relallvisible; + NullableDatum relallfrozen; +} RelationStatsValues; + +/* + * Statistics values applied to pg_statistic during stats import or restore. + * + * A field with isnull set to true leaves the corresponding statistics kind + * unset. The caller must initialize every field. + * + * The "version" field is currently ignored. In the future, it can be used to + * interpret the format of older statistics. + */ +typedef struct AttributeStatsValues +{ + NullableDatum version; + NullableDatum null_frac; + NullableDatum avg_width; + NullableDatum n_distinct; + NullableDatum most_common_vals; + NullableDatum most_common_freqs; + NullableDatum histogram_bounds; + NullableDatum correlation; + NullableDatum most_common_elems; + NullableDatum most_common_elem_freqs; + NullableDatum elem_count_histogram; + NullableDatum range_length_histogram; + NullableDatum range_empty_frac; + NullableDatum range_bounds_histogram; +} AttributeStatsValues; + extern bool import_relation_statistics(Relation rel, - const NullableDatum *version, - const NullableDatum *relpages, - const NullableDatum *reltuples, - const NullableDatum *relallvisible, - const NullableDatum *relallfrozen); + const RelationStatsValues *statvalues); extern bool import_attribute_statistics(Relation rel, AttrNumber attnum, bool inherited, - const NullableDatum *version, - const NullableDatum *null_frac, - const NullableDatum *avg_width, - const NullableDatum *n_distinct, - const NullableDatum *most_common_vals, - const NullableDatum *most_common_freqs, - const NullableDatum *histogram_bounds, - const NullableDatum *correlation, - const NullableDatum *most_common_elems, - const NullableDatum *most_common_elem_freqs, - const NullableDatum *elem_count_histogram, - const NullableDatum *range_length_histogram, - const NullableDatum *range_empty_frac, - const NullableDatum *range_bounds_histogram); + const AttributeStatsValues *statvalues); extern bool delete_attribute_statistics(Relation rel, AttrNumber attnum, bool inherited); diff --git a/src/backend/statistics/attribute_stats.c b/src/backend/statistics/attribute_stats.c index 5bb33e4283ae..1d19827dc45e 100644 --- a/src/backend/statistics/attribute_stats.c +++ b/src/backend/statistics/attribute_stats.c @@ -109,7 +109,7 @@ static bool attribute_statistics_update_internal(Oid reloid, const char *attname, AttrNumber attnum, bool inherited, - const NullableDatum *args); + const AttributeStatsValues *statvalues); static void upsert_pg_statistic(Relation starel, HeapTuple oldtup, const Datum *values, const bool *nulls, const bool *replaces); static bool delete_pg_statistic(Oid reloid, AttrNumber attnum, bool stainherit); @@ -140,6 +140,7 @@ attribute_statistics_update(const NullableDatum *args) AttrNumber attnum; bool inherited; Oid locked_table = InvalidOid; + AttributeStatsValues values; stats_check_required_arg(args, attarginfo, ATTRELSCHEMA_ARG); stats_check_required_arg(args, attarginfo, ATTRELNAME_ARG); @@ -204,8 +205,25 @@ attribute_statistics_update(const NullableDatum *args) stats_check_required_arg(args, attarginfo, INHERITED_ARG); inherited = DatumGetBool(args[INHERITED_ARG].value); + /* Collect the values to apply */ + values.version.value = (Datum) 0; + values.version.isnull = true; + values.null_frac = args[NULL_FRAC_ARG]; + values.avg_width = args[AVG_WIDTH_ARG]; + values.n_distinct = args[N_DISTINCT_ARG]; + values.most_common_vals = args[MOST_COMMON_VALS_ARG]; + values.most_common_freqs = args[MOST_COMMON_FREQS_ARG]; + values.histogram_bounds = args[HISTOGRAM_BOUNDS_ARG]; + values.correlation = args[CORRELATION_ARG]; + values.most_common_elems = args[MOST_COMMON_ELEMS_ARG]; + values.most_common_elem_freqs = args[MOST_COMMON_ELEM_FREQS_ARG]; + values.elem_count_histogram = args[ELEM_COUNT_HISTOGRAM_ARG]; + values.range_length_histogram = args[RANGE_LENGTH_HISTOGRAM_ARG]; + values.range_empty_frac = args[RANGE_EMPTY_FRAC_ARG]; + values.range_bounds_histogram = args[RANGE_BOUNDS_HISTOGRAM_ARG]; + return attribute_statistics_update_internal(reloid, attname, attnum, - inherited, args); + inherited, &values); } /* @@ -214,7 +232,8 @@ attribute_statistics_update(const NullableDatum *args) static bool attribute_statistics_update_internal(Oid reloid, const char *attname, AttrNumber attnum, - bool inherited, const NullableDatum *args) + bool inherited, + const AttributeStatsValues *statvalues) { Relation starel; HeapTuple statup; @@ -231,16 +250,16 @@ attribute_statistics_update_internal(Oid reloid, FmgrInfo array_in_fn; - bool do_mcv = !args[MOST_COMMON_FREQS_ARG].isnull && - !args[MOST_COMMON_VALS_ARG].isnull; - bool do_histogram = !args[HISTOGRAM_BOUNDS_ARG].isnull; - bool do_correlation = !args[CORRELATION_ARG].isnull; - bool do_mcelem = !args[MOST_COMMON_ELEMS_ARG].isnull && - !args[MOST_COMMON_ELEM_FREQS_ARG].isnull; - bool do_dechist = !args[ELEM_COUNT_HISTOGRAM_ARG].isnull; - bool do_bounds_histogram = !args[RANGE_BOUNDS_HISTOGRAM_ARG].isnull; - bool do_range_length_histogram = !args[RANGE_LENGTH_HISTOGRAM_ARG].isnull && - !args[RANGE_EMPTY_FRAC_ARG].isnull; + bool do_mcv = !statvalues->most_common_freqs.isnull && + !statvalues->most_common_vals.isnull; + bool do_histogram = !statvalues->histogram_bounds.isnull; + bool do_correlation = !statvalues->correlation.isnull; + bool do_mcelem = !statvalues->most_common_elems.isnull && + !statvalues->most_common_elem_freqs.isnull; + bool do_dechist = !statvalues->elem_count_histogram.isnull; + bool do_bounds_histogram = !statvalues->range_bounds_histogram.isnull; + bool do_range_length_histogram = !statvalues->range_length_histogram.isnull && + !statvalues->range_empty_frac.isnull; Datum values[Natts_pg_statistic] = {0}; bool nulls[Natts_pg_statistic] = {0}; @@ -253,41 +272,45 @@ attribute_statistics_update_internal(Oid reloid, * and skip the corresponding statistics kind, reporting back a failure. */ - if (!stats_check_arg_array(args, attarginfo, MOST_COMMON_FREQS_ARG)) + if (!stats_check_arg_array(&statvalues->most_common_freqs, + "most_common_freqs")) { do_mcv = false; result = false; } - if (!stats_check_arg_array(args, attarginfo, MOST_COMMON_ELEM_FREQS_ARG)) + if (!stats_check_arg_array(&statvalues->most_common_elem_freqs, + "most_common_elem_freqs")) { do_mcelem = false; result = false; } - if (!stats_check_arg_array(args, attarginfo, ELEM_COUNT_HISTOGRAM_ARG)) + if (!stats_check_arg_array(&statvalues->elem_count_histogram, + "elem_count_histogram")) { do_dechist = false; result = false; } - if (!stats_check_arg_pair(args, attarginfo, - MOST_COMMON_VALS_ARG, MOST_COMMON_FREQS_ARG)) + if (!stats_check_arg_pair(&statvalues->most_common_vals, + &statvalues->most_common_freqs, + "most_common_vals", "most_common_freqs")) { do_mcv = false; result = false; } - if (!stats_check_arg_pair(args, attarginfo, - MOST_COMMON_ELEMS_ARG, - MOST_COMMON_ELEM_FREQS_ARG)) + if (!stats_check_arg_pair(&statvalues->most_common_elems, + &statvalues->most_common_elem_freqs, + "most_common_elems", "most_common_elem_freqs")) { do_mcelem = false; result = false; } - if (!stats_check_arg_pair(args, attarginfo, - RANGE_LENGTH_HISTOGRAM_ARG, - RANGE_EMPTY_FRAC_ARG)) + if (!stats_check_arg_pair(&statvalues->range_length_histogram, + &statvalues->range_empty_frac, + "range_length_histogram", "range_empty_frac")) { do_range_length_histogram = false; result = false; @@ -361,19 +384,19 @@ attribute_statistics_update_internal(Oid reloid, replaces); /* if specified, set to argument values */ - if (!args[NULL_FRAC_ARG].isnull) + if (!statvalues->null_frac.isnull) { - values[Anum_pg_statistic_stanullfrac - 1] = args[NULL_FRAC_ARG].value; + values[Anum_pg_statistic_stanullfrac - 1] = statvalues->null_frac.value; replaces[Anum_pg_statistic_stanullfrac - 1] = true; } - if (!args[AVG_WIDTH_ARG].isnull) + if (!statvalues->avg_width.isnull) { - values[Anum_pg_statistic_stawidth - 1] = args[AVG_WIDTH_ARG].value; + values[Anum_pg_statistic_stawidth - 1] = statvalues->avg_width.value; replaces[Anum_pg_statistic_stawidth - 1] = true; } - if (!args[N_DISTINCT_ARG].isnull) + if (!statvalues->n_distinct.isnull) { - values[Anum_pg_statistic_stadistinct - 1] = args[N_DISTINCT_ARG].value; + values[Anum_pg_statistic_stadistinct - 1] = statvalues->n_distinct.value; replaces[Anum_pg_statistic_stadistinct - 1] = true; } @@ -381,10 +404,10 @@ attribute_statistics_update_internal(Oid reloid, if (do_mcv) { bool converted; - Datum stanumbers = args[MOST_COMMON_FREQS_ARG].value; + Datum stanumbers = statvalues->most_common_freqs.value; Datum stavalues = statatt_build_stavalues("most_common_vals", &array_in_fn, - args[MOST_COMMON_VALS_ARG].value, + statvalues->most_common_vals.value, atttypid, atttypmod, &converted); @@ -424,7 +447,7 @@ attribute_statistics_update_internal(Oid reloid, stavalues = statatt_build_stavalues("histogram_bounds", &array_in_fn, - args[HISTOGRAM_BOUNDS_ARG].value, + statvalues->histogram_bounds.value, atttypid, atttypmod, &converted); @@ -442,7 +465,7 @@ attribute_statistics_update_internal(Oid reloid, /* STATISTIC_KIND_CORRELATION */ if (do_correlation) { - Datum elems[] = {args[CORRELATION_ARG].value}; + Datum elems[] = {statvalues->correlation.value}; ArrayType *arry = construct_array_builtin(elems, 1, FLOAT4OID); Datum stanumbers = PointerGetDatum(arry); @@ -455,13 +478,13 @@ attribute_statistics_update_internal(Oid reloid, /* STATISTIC_KIND_MCELEM */ if (do_mcelem) { - Datum stanumbers = args[MOST_COMMON_ELEM_FREQS_ARG].value; + Datum stanumbers = statvalues->most_common_elem_freqs.value; bool converted = false; Datum stavalues; stavalues = statatt_build_stavalues("most_common_elems", &array_in_fn, - args[MOST_COMMON_ELEMS_ARG].value, + statvalues->most_common_elems.value, elemtypid, atttypmod, &converted); @@ -479,7 +502,7 @@ attribute_statistics_update_internal(Oid reloid, /* STATISTIC_KIND_DECHIST */ if (do_dechist) { - Datum stanumbers = args[ELEM_COUNT_HISTOGRAM_ARG].value; + Datum stanumbers = statvalues->elem_count_histogram.value; statatt_set_slot(values, nulls, replaces, STATISTIC_KIND_DECHIST, @@ -509,7 +532,7 @@ attribute_statistics_update_internal(Oid reloid, stavalues = statatt_build_stavalues("range_bounds_histogram", &array_in_fn, - args[RANGE_BOUNDS_HISTOGRAM_ARG].value, + statvalues->range_bounds_histogram.value, bounds_typid, atttypmod, &converted); @@ -529,7 +552,7 @@ attribute_statistics_update_internal(Oid reloid, if (do_range_length_histogram) { /* The anyarray is always a float8[] for this stakind */ - Datum elems[] = {args[RANGE_EMPTY_FRAC_ARG].value}; + Datum elems[] = {statvalues->range_empty_frac.value}; ArrayType *arry = construct_array_builtin(elems, 1, FLOAT4OID); Datum stanumbers = PointerGetDatum(arry); @@ -538,7 +561,7 @@ attribute_statistics_update_internal(Oid reloid, stavalues = statatt_build_stavalues("range_length_histogram", &array_in_fn, - args[RANGE_LENGTH_HISTOGRAM_ARG].value, + statvalues->range_length_histogram.value, FLOAT8OID, 0, &converted); if (converted) @@ -713,48 +736,19 @@ pg_restore_attribute_stats(PG_FUNCTION_ARGS) } /* - * Import attribute statistics from NullableDatum inputs for all statistical - * values. + * Import attribute statistics for a relation. * - * For now, the 'version' argument is ignored. In the future it can be used - * to interpret older statistics properly. + * See AttributeStatsValues for the values to provide. */ bool import_attribute_statistics(Relation rel, AttrNumber attnum, bool inherited, - const NullableDatum *version, - const NullableDatum *null_frac, - const NullableDatum *avg_width, - const NullableDatum *n_distinct, - const NullableDatum *most_common_vals, - const NullableDatum *most_common_freqs, - const NullableDatum *histogram_bounds, - const NullableDatum *correlation, - const NullableDatum *most_common_elems, - const NullableDatum *most_common_elem_freqs, - const NullableDatum *elem_count_histogram, - const NullableDatum *range_length_histogram, - const NullableDatum *range_empty_frac, - const NullableDatum *range_bounds_histogram) + const AttributeStatsValues *statvalues) { - NullableDatum args[NUM_ATTRIBUTE_STATS_ARGS]; Oid reloid = RelationGetRelid(rel); char *relname = RelationGetRelationName(rel); char *attname = get_attname(reloid, attnum, true); - NullableDatum unused = {.isnull = true, .value = (Datum) 0}; - Assert(null_frac); - Assert(avg_width); - Assert(n_distinct); - Assert(most_common_vals); - Assert(most_common_freqs); - Assert(histogram_bounds); - Assert(correlation); - Assert(most_common_elems); - Assert(most_common_elem_freqs); - Assert(elem_count_histogram); - Assert(range_length_histogram); - Assert(range_empty_frac); - Assert(range_bounds_histogram); + Assert(statvalues); /* annoyingly, get_attname doesn't check attisdropped */ if (attname == NULL || @@ -764,28 +758,8 @@ import_attribute_statistics(Relation rel, AttrNumber attnum, bool inherited, errmsg("column %d of relation \"%s\" does not exist", attnum, relname))); - args[ATTRELSCHEMA_ARG] = unused; - args[ATTRELNAME_ARG] = unused; - args[ATTNAME_ARG] = unused; - args[ATTNUM_ARG] = unused; - args[INHERITED_ARG] = unused; - - args[NULL_FRAC_ARG] = *null_frac; - args[AVG_WIDTH_ARG] = *avg_width; - args[N_DISTINCT_ARG] = *n_distinct; - args[MOST_COMMON_VALS_ARG] = *most_common_vals; - args[MOST_COMMON_FREQS_ARG] = *most_common_freqs; - args[HISTOGRAM_BOUNDS_ARG] = *histogram_bounds; - args[CORRELATION_ARG] = *correlation; - args[MOST_COMMON_ELEMS_ARG] = *most_common_elems; - args[MOST_COMMON_ELEM_FREQS_ARG] = *most_common_elem_freqs; - args[ELEM_COUNT_HISTOGRAM_ARG] = *elem_count_histogram; - args[RANGE_LENGTH_HISTOGRAM_ARG] = *range_length_histogram; - args[RANGE_EMPTY_FRAC_ARG] = *range_empty_frac; - args[RANGE_BOUNDS_HISTOGRAM_ARG] = *range_bounds_histogram; - return attribute_statistics_update_internal(reloid, attname, attnum, - inherited, args); + inherited, statvalues); } /* diff --git a/src/backend/statistics/relation_stats.c b/src/backend/statistics/relation_stats.c index 392aeed5d253..28d87fa6f77d 100644 --- a/src/backend/statistics/relation_stats.c +++ b/src/backend/statistics/relation_stats.c @@ -61,7 +61,7 @@ static struct StatsArgInfo relarginfo[] = static bool relation_statistics_update(const NullableDatum *args); static bool relation_statistics_update_internal(Oid reloid, - const NullableDatum *args); + const RelationStatsValues *statvalues); /* * Internal function for modifying statistics for a relation. @@ -73,6 +73,7 @@ relation_statistics_update(const NullableDatum *args) char *relname; Oid reloid; Oid locked_table = InvalidOid; + RelationStatsValues values; stats_check_required_arg(args, relarginfo, RELSCHEMA_ARG); stats_check_required_arg(args, relarginfo, RELNAME_ARG); @@ -90,14 +91,23 @@ relation_statistics_update(const NullableDatum *args) ShareUpdateExclusiveLock, 0, RangeVarCallbackForStats, &locked_table); - return relation_statistics_update_internal(reloid, args); + /* Collect the values to apply. */ + values.version.value = (Datum) 0; + values.version.isnull = true; + values.relpages = args[RELPAGES_ARG]; + values.reltuples = args[RELTUPLES_ARG]; + values.relallvisible = args[RELALLVISIBLE_ARG]; + values.relallfrozen = args[RELALLFROZEN_ARG]; + + return relation_statistics_update_internal(reloid, &values); } /* * Workhorse function for relation_statistics_update. */ static bool -relation_statistics_update_internal(Oid reloid, const NullableDatum *args) +relation_statistics_update_internal(Oid reloid, + const RelationStatsValues *statvalues) { int32 relpages = 0; bool update_relpages = false; @@ -116,15 +126,15 @@ relation_statistics_update_internal(Oid reloid, const NullableDatum *args) int nreplaces = 0; bool result = true; - if (!args[RELPAGES_ARG].isnull) + if (!statvalues->relpages.isnull) { - relpages = DatumGetInt32(args[RELPAGES_ARG].value); + relpages = DatumGetInt32(statvalues->relpages.value); update_relpages = true; } - if (!args[RELTUPLES_ARG].isnull) + if (!statvalues->reltuples.isnull) { - reltuples = DatumGetFloat4(args[RELTUPLES_ARG].value); + reltuples = DatumGetFloat4(statvalues->reltuples.value); if (isnan(reltuples) || isinf(reltuples)) { ereport(WARNING, @@ -143,15 +153,15 @@ relation_statistics_update_internal(Oid reloid, const NullableDatum *args) update_reltuples = true; } - if (!args[RELALLVISIBLE_ARG].isnull) + if (!statvalues->relallvisible.isnull) { - relallvisible = DatumGetInt32(args[RELALLVISIBLE_ARG].value); + relallvisible = DatumGetInt32(statvalues->relallvisible.value); update_relallvisible = true; } - if (!args[RELALLFROZEN_ARG].isnull) + if (!statvalues->relallfrozen.isnull) { - relallfrozen = DatumGetInt32(args[RELALLFROZEN_ARG].value); + relallfrozen = DatumGetInt32(statvalues->relallfrozen.value); update_relallfrozen = true; } @@ -259,35 +269,15 @@ pg_restore_relation_stats(PG_FUNCTION_ARGS) } /* - * Import relation statistics from NullableDatum inputs for all statistical - * values. + * Import relation statistics. * - * For now, the 'version' argument is ignored. In the future it can be used - * to interpret older statistics properly. + * See RelationStatsValues for the values to provide. */ bool -import_relation_statistics(Relation rel, - const NullableDatum *version, - const NullableDatum *relpages, - const NullableDatum *reltuples, - const NullableDatum *relallvisible, - const NullableDatum *relallfrozen) +import_relation_statistics(Relation rel, const RelationStatsValues *statvalues) { - NullableDatum args[NUM_RELATION_STATS_ARGS]; - NullableDatum unused = {.isnull = true, .value = (Datum) 0}; + Assert(statvalues); - Assert(relpages); - Assert(reltuples); - Assert(relallvisible); - Assert(relallfrozen); - - args[RELSCHEMA_ARG] = unused; - args[RELNAME_ARG] = unused; - - args[RELPAGES_ARG] = *relpages; - args[RELTUPLES_ARG] = *reltuples; - args[RELALLVISIBLE_ARG] = *relallvisible; - args[RELALLFROZEN_ARG] = *relallfrozen; - - return relation_statistics_update_internal(RelationGetRelid(rel), args); + return relation_statistics_update_internal(RelationGetRelid(rel), + statvalues); } diff --git a/src/backend/statistics/stat_utils.c b/src/backend/statistics/stat_utils.c index e12678311f46..1cd00959b5ca 100644 --- a/src/backend/statistics/stat_utils.c +++ b/src/backend/statistics/stat_utils.c @@ -70,23 +70,21 @@ stats_check_required_arg(const NullableDatum *args, * true. */ bool -stats_check_arg_array(const NullableDatum *args, - struct StatsArgInfo *arginfo, - int argnum) +stats_check_arg_array(const NullableDatum *arg, const char *argname) { ArrayType *arr; - if (args[argnum].isnull) + if (arg->isnull) return true; - arr = DatumGetArrayTypeP(args[argnum].value); + arr = DatumGetArrayTypeP(arg->value); if (ARR_NDIM(arr) != 1) { ereport(WARNING, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("argument \"%s\" must not be a multidimensional array", - arginfo[argnum].argname))); + argname))); return false; } @@ -95,7 +93,7 @@ stats_check_arg_array(const NullableDatum *args, ereport(WARNING, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("argument \"%s\" array must not contain null values", - arginfo[argnum].argname))); + argname))); return false; } @@ -111,23 +109,21 @@ stats_check_arg_array(const NullableDatum *args, * true. */ bool -stats_check_arg_pair(const NullableDatum *args, - struct StatsArgInfo *arginfo, - int argnum1, int argnum2) +stats_check_arg_pair(const NullableDatum *arg1, const NullableDatum *arg2, + const char *argname1, const char *argname2) { - if (args[argnum1].isnull && args[argnum2].isnull) + if (arg1->isnull && arg2->isnull) return true; - if (args[argnum1].isnull || args[argnum2].isnull) + if (arg1->isnull || arg2->isnull) { - int nullarg = args[argnum1].isnull ? argnum1 : argnum2; - int otherarg = args[argnum1].isnull ? argnum2 : argnum1; + const char *nullarg = arg1->isnull ? argname1 : argname2; + const char *otherarg = arg1->isnull ? argname2 : argname1; ereport(WARNING, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("argument \"%s\" must be specified when argument \"%s\" is specified", - arginfo[nullarg].argname, - arginfo[otherarg].argname))); + nullarg, otherarg))); return false; } diff --git a/contrib/postgres_fdw/postgres_fdw.c b/contrib/postgres_fdw/postgres_fdw.c index 9269418a074c..2cc594aecb69 100644 --- a/contrib/postgres_fdw/postgres_fdw.c +++ b/contrib/postgres_fdw/postgres_fdw.c @@ -6253,11 +6253,12 @@ import_fetched_statistics(Relation relation, int attrcnt) { PGresult *res; - NullableDatum args[ATTSTATS_NUM_FIELDS]; + NullableDatum version; + RelationStatsValues relvalues; - /* Set the 'version' parameter, which is common to both statistics. */ - args[0].value = Int32GetDatum(remstats->version); - args[0].isnull = false; + /* Set the 'version' value, which is common to both statistics. */ + version.value = Int32GetDatum(remstats->version); + version.isnull = false; /* * We import attribute statistics first, if any, because those are more @@ -6274,6 +6275,7 @@ import_fetched_statistics(Relation relation, { int row = remattrmap[mapidx].res_index; AttrNumber attnum = remattrmap[mapidx].local_attnum; + AttributeStatsValues attvalues; /* All mappings should have been assigned a result set row. */ Assert(row >= 0); @@ -6284,41 +6286,38 @@ import_fetched_statistics(Relation relation, /* Clear existing attribute statistics. */ delete_attribute_statistics(relation, attnum, false); - /* Set the remaining parameters. */ - set_float_arg(&args[1], + /* Set the remaining values. */ + attvalues.version = version; + set_float_arg(&attvalues.null_frac, get_opt_value(res, row, ATTSTATS_NULL_FRAC)); - set_int32_arg(&args[2], + set_int32_arg(&attvalues.avg_width, get_opt_value(res, row, ATTSTATS_AVG_WIDTH)); - set_float_arg(&args[3], + set_float_arg(&attvalues.n_distinct, get_opt_value(res, row, ATTSTATS_N_DISTINCT)); - set_text_arg(&args[4], + set_text_arg(&attvalues.most_common_vals, get_opt_value(res, row, ATTSTATS_MOST_COMMON_VALS)); - set_floatarr_arg(&args[5], + set_floatarr_arg(&attvalues.most_common_freqs, get_opt_value(res, row, ATTSTATS_MOST_COMMON_FREQS)); - set_text_arg(&args[6], + set_text_arg(&attvalues.histogram_bounds, get_opt_value(res, row, ATTSTATS_HISTOGRAM_BOUNDS)); - set_float_arg(&args[7], + set_float_arg(&attvalues.correlation, get_opt_value(res, row, ATTSTATS_CORRELATION)); - set_text_arg(&args[8], + set_text_arg(&attvalues.most_common_elems, get_opt_value(res, row, ATTSTATS_MOST_COMMON_ELEMS)); - set_floatarr_arg(&args[9], + set_floatarr_arg(&attvalues.most_common_elem_freqs, get_opt_value(res, row, ATTSTATS_MOST_COMMON_ELEM_FREQS)); - set_floatarr_arg(&args[10], + set_floatarr_arg(&attvalues.elem_count_histogram, get_opt_value(res, row, ATTSTATS_ELEM_COUNT_HISTOGRAM)); - set_text_arg(&args[11], + set_text_arg(&attvalues.range_length_histogram, get_opt_value(res, row, ATTSTATS_RANGE_LENGTH_HISTOGRAM)); - set_float_arg(&args[12], + set_float_arg(&attvalues.range_empty_frac, get_opt_value(res, row, ATTSTATS_RANGE_EMPTY_FRAC)); - set_text_arg(&args[13], + set_text_arg(&attvalues.range_bounds_histogram, get_opt_value(res, row, ATTSTATS_RANGE_BOUNDS_HISTOGRAM)); /* Try to import the statistics. */ if (!import_attribute_statistics(relation, attnum, false, - &args[0], &args[1], &args[2], - &args[3], &args[4], &args[5], - &args[6], &args[7], &args[8], - &args[9], &args[10], &args[11], - &args[12], &args[13])) + &attvalues)) { ereport(WARNING, errmsg("could not import statistics for foreign table \"%s.%s\" --- attribute statistics import failed for column \"%s\" of this foreign table", @@ -6337,20 +6336,22 @@ import_fetched_statistics(Relation relation, Assert(PQnfields(res) == RELSTATS_NUM_FIELDS); Assert(PQntuples(res) == 1); - /* Set the remaining parameters. */ - set_int32_arg(&args[1], get_opt_value(res, 0, RELSTATS_RELPAGES)); - Assert(!args[1].isnull); - set_float_arg(&args[2], get_opt_value(res, 0, RELSTATS_RELTUPLES)); - Assert(!args[2].isnull); + /* Set the remaining values. */ + relvalues.version = version; + set_int32_arg(&relvalues.relpages, + get_opt_value(res, 0, RELSTATS_RELPAGES)); + Assert(!relvalues.relpages.isnull); + set_float_arg(&relvalues.reltuples, + get_opt_value(res, 0, RELSTATS_RELTUPLES)); + Assert(!relvalues.reltuples.isnull); /* We don't import relallvisible/relallfrozen. */ - args[3].value = (Datum) 0; - args[3].isnull = true; - args[4].value = (Datum) 0; - args[4].isnull = true; + relvalues.relallvisible.value = (Datum) 0; + relvalues.relallvisible.isnull = true; + relvalues.relallfrozen.value = (Datum) 0; + relvalues.relallfrozen.isnull = true; /* Try to import the statistics. */ - if (!import_relation_statistics(relation, &args[0], &args[1], - &args[2], &args[3], &args[4])) + if (!import_relation_statistics(relation, &relvalues)) { ereport(WARNING, errmsg("could not import statistics for foreign table \"%s.%s\" --- relation statistics import failed for this foreign table", diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list index c546b3d6375d..fb3ee1b071b5 100644 --- a/src/tools/pgindent/typedefs.list +++ b/src/tools/pgindent/typedefs.list @@ -185,6 +185,7 @@ AttrMissing AttrNumber AttrResultArgMap AttributeOpts +AttributeStatsValues AuthRequest AuthToken AutoPrewarmReadStreamData @@ -2622,6 +2623,7 @@ Relation RelationData RelationInfo RelationPtr +RelationStatsValues RelationSyncEntry RelcacheCallbackFunction ReleaseMatchCB -- 2.55.0