From c949ee76a7c561015534a720e9d97d3bd7cc17ba Mon Sep 17 00:00:00 2001 From: Corey Huinker Date: Mon, 3 Aug 2026 15:59:40 -0400 Subject: [PATCH v3 14/15] Refactor attribute_stats update functions. Move all functionality from attribute_statistics_update() to pg_restore_attribute_stats() and then rename attribute_statistics_update_internal() to attribute_statistics_update(). --- src/backend/statistics/attribute_stats.c | 267 +++++++++++------------ 1 file changed, 126 insertions(+), 141 deletions(-) diff --git a/src/backend/statistics/attribute_stats.c b/src/backend/statistics/attribute_stats.c index 348ccc355df..a6710d6ef50 100644 --- a/src/backend/statistics/attribute_stats.c +++ b/src/backend/statistics/attribute_stats.c @@ -32,7 +32,7 @@ /* * Positional argument numbers, names, and types for - * attribute_statistics_update() and pg_restore_attribute_stats(). + * pg_restore_attribute_stats(). */ enum attribute_stats_argnum @@ -106,25 +106,24 @@ static struct StatsArgInfo cleararginfo[] = [C_ATTARG_NUM_ATTARGS] = {0} }; -static bool attribute_statistics_update(const NullableDatum *args); -static bool attribute_statistics_update_internal(Oid reloid, - const char *attname, - 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); +static bool attribute_statistics_update(Oid reloid, + const char *attname, + 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); 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); @@ -146,112 +145,23 @@ static bool delete_pg_statistic(Oid reloid, AttrNumber attnum, bool stainherit); * and other statistic kinds may still be updated. */ static bool -attribute_statistics_update(const NullableDatum *args) -{ - char *nspname; - char *relname; - Oid reloid; - char *attname; - AttrNumber attnum; - bool inherited; - - stats_check_required_arg(&args[ATTARG_ATTRELSCHEMA], attarginfo[ATTARG_ATTRELSCHEMA].argname); - stats_check_required_arg(&args[ATTARG_ATTRELNAME], attarginfo[ATTARG_ATTRELNAME].argname); - - nspname = TextDatumGetCString(args[ATTARG_ATTRELSCHEMA].value); - relname = TextDatumGetCString(args[ATTARG_ATTRELNAME].value); - - stats_check_recovery(ERROR); - - /* lock before looking up attribute */ - reloid = stats_check_lock_relation(nspname, relname); - - /* user can specify either attname or attnum, but not both */ - if (!args[ATTARG_ATTNAME].isnull) - { - if (!args[ATTARG_ATTNUM].isnull) - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("cannot specify both \"%s\" and \"%s\"", "attname", "attnum"))); - attname = TextDatumGetCString(args[ATTARG_ATTNAME].value); - attnum = get_attnum(reloid, attname); - /* note that this test covers attisdropped cases too: */ - if (attnum == InvalidAttrNumber) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_COLUMN), - errmsg("column \"%s\" of relation \"%s\" does not exist", - attname, relname))); - } - else if (!args[ATTARG_ATTNUM].isnull) - { - attnum = DatumGetInt16(args[ATTARG_ATTNUM].value); - attname = get_attname(reloid, attnum, true); - /* annoyingly, get_attname doesn't check attisdropped */ - if (attname == NULL || - !SearchSysCacheExistsAttName(reloid, attname)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_COLUMN), - errmsg("column %d of relation \"%s\" does not exist", - attnum, relname))); - } - else - { - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("must specify either \"%s\" or \"%s\"", "attname", "attnum"))); - attname = NULL; /* keep compiler quiet */ - attnum = 0; - } - - if (attnum < 0) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("cannot modify statistics on system column \"%s\"", - attname))); - - stats_check_required_arg(&args[ATTARG_INHERITED], attarginfo[ATTARG_INHERITED].argname); - inherited = DatumGetBool(args[ATTARG_INHERITED].value); - - return attribute_statistics_update_internal(reloid, attname, attnum, - inherited, - &args[ATTARG_VERSION], - &args[ATTARG_NULL_FRAC], - &args[ATTARG_AVG_WIDTH], - &args[ATTARG_N_DISTINCT], - &args[ATTARG_MOST_COMMON_VALS], - &args[ATTARG_MOST_COMMON_FREQS], - &args[ATTARG_HISTOGRAM_BOUNDS], - &args[ATTARG_CORRELATION], - &args[ATTARG_MOST_COMMON_ELEMS], - &args[ATTARG_MOST_COMMON_ELEM_FREQS], - &args[ATTARG_ELEM_COUNT_HISTOGRAM], - &args[ATTARG_RANGE_LENGTH_HISTOGRAM], - &args[ATTARG_RANGE_EMPTY_FRAC], - &args[ATTARG_RANGE_BOUNDS_HISTOGRAM] - ); -} - -/* - * Workhorse function for attribute_statistics_update. - */ -static bool -attribute_statistics_update_internal(Oid reloid, - const char *attname, 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) +attribute_statistics_update(Oid reloid, + const char *attname, 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) { Relation starel; HeapTuple statup; @@ -725,14 +635,91 @@ pg_clear_attribute_stats(PG_FUNCTION_ARGS) Datum pg_restore_attribute_stats(PG_FUNCTION_ARGS) { - NullableDatum positional_args[ATTARG_NUM_ATTARGS]; + NullableDatum args[ATTARG_NUM_ATTARGS]; bool result = true; + char *nspname; + char *relname; + Oid reloid; + char *attname; + AttrNumber attnum; + bool inherited; - if (!stats_fill_args_from_arg_pairs(fcinfo, positional_args, + if (!stats_fill_args_from_arg_pairs(fcinfo, args, attarginfo)) result = false; - if (!attribute_statistics_update(positional_args)) + stats_check_required_arg(&args[ATTARG_ATTRELSCHEMA], attarginfo[ATTARG_ATTRELSCHEMA].argname); + stats_check_required_arg(&args[ATTARG_ATTRELNAME], attarginfo[ATTARG_ATTRELNAME].argname); + + nspname = TextDatumGetCString(args[ATTARG_ATTRELSCHEMA].value); + relname = TextDatumGetCString(args[ATTARG_ATTRELNAME].value); + + stats_check_recovery(ERROR); + + /* lock before looking up attribute */ + reloid = stats_check_lock_relation(nspname, relname); + + /* user can specify either attname or attnum, but not both */ + if (!args[ATTARG_ATTNAME].isnull) + { + if (!args[ATTARG_ATTNUM].isnull) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("cannot specify both \"%s\" and \"%s\"", "attname", "attnum"))); + attname = TextDatumGetCString(args[ATTARG_ATTNAME].value); + attnum = get_attnum(reloid, attname); + /* note that this test covers attisdropped cases too: */ + if (attnum == InvalidAttrNumber) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_COLUMN), + errmsg("column \"%s\" of relation \"%s\" does not exist", + attname, relname))); + } + else if (!args[ATTARG_ATTNUM].isnull) + { + attnum = DatumGetInt16(args[ATTARG_ATTNUM].value); + attname = get_attname(reloid, attnum, true); + /* annoyingly, get_attname doesn't check attisdropped */ + if (attname == NULL || + !SearchSysCacheExistsAttName(reloid, attname)) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_COLUMN), + errmsg("column %d of relation \"%s\" does not exist", + attnum, relname))); + } + else + { + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("must specify either \"%s\" or \"%s\"", "attname", "attnum"))); + attname = NULL; /* keep compiler quiet */ + attnum = 0; + } + + if (attnum < 0) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot modify statistics on system column \"%s\"", + attname))); + + stats_check_required_arg(&args[ATTARG_INHERITED], attarginfo[ATTARG_INHERITED].argname); + inherited = DatumGetBool(args[ATTARG_INHERITED].value); + + if (!attribute_statistics_update(reloid, attname, attnum, inherited, + &args[ATTARG_VERSION], + &args[ATTARG_NULL_FRAC], + &args[ATTARG_AVG_WIDTH], + &args[ATTARG_N_DISTINCT], + &args[ATTARG_MOST_COMMON_VALS], + &args[ATTARG_MOST_COMMON_FREQS], + &args[ATTARG_HISTOGRAM_BOUNDS], + &args[ATTARG_CORRELATION], + &args[ATTARG_MOST_COMMON_ELEMS], + &args[ATTARG_MOST_COMMON_ELEM_FREQS], + &args[ATTARG_ELEM_COUNT_HISTOGRAM], + &args[ATTARG_RANGE_LENGTH_HISTOGRAM], + &args[ATTARG_RANGE_EMPTY_FRAC], + &args[ATTARG_RANGE_BOUNDS_HISTOGRAM])) result = false; PG_RETURN_BOOL(result); @@ -793,18 +780,16 @@ import_attribute_statistics(Relation rel, AttrNumber attnum, bool inherited, errmsg("column %d of relation \"%s\" does not exist", attnum, relname))); - return attribute_statistics_update_internal(reloid, attname, attnum, - inherited, version, - null_frac, avg_width, - n_distinct, most_common_vals, - most_common_freqs, - histogram_bounds, correlation, - most_common_elems, - most_common_elem_freqs, - elem_count_histogram, - range_length_histogram, - range_empty_frac, - range_bounds_histogram); + return attribute_statistics_update(reloid, attname, attnum, inherited, + version, null_frac, avg_width, + n_distinct, most_common_vals, + most_common_freqs, histogram_bounds, + correlation, most_common_elems, + most_common_elem_freqs, + elem_count_histogram, + range_length_histogram, + range_empty_frac, + range_bounds_histogram); } /* -- 2.50.1 (Apple Git-155)