From 90e69b3ce852e2b626b0eaa90299b3329cec0bae Mon Sep 17 00:00:00 2001 From: Corey Huinker Date: Fri, 31 Jul 2026 16:44:25 -0400 Subject: [PATCH v3 10/15] Decouple stats_check_* functions from StatsArgInfo structure. Change stats_check_required_arg(), stats_check_arg_array(), and stats_check_arg_pair() to stop using an array of StatsArgInfo plus an index to just using a NullableDatum with a char string name provided. This allows the functions to be useful in situations where there isn't an array of NullableDatum ordered by a given StatsArgInfo. --- src/backend/statistics/attribute_stats.c | 40 ++++++------ src/backend/statistics/extended_stats_funcs.c | 20 +++--- src/backend/statistics/relation_stats.c | 4 +- src/backend/statistics/stat_utils.c | 61 ++++++++++--------- src/include/statistics/stat_utils.h | 15 +++-- 5 files changed, 72 insertions(+), 68 deletions(-) diff --git a/src/backend/statistics/attribute_stats.c b/src/backend/statistics/attribute_stats.c index 4ee14b3ebdf..d053d91e5dc 100644 --- a/src/backend/statistics/attribute_stats.c +++ b/src/backend/statistics/attribute_stats.c @@ -143,8 +143,8 @@ attribute_statistics_update(const NullableDatum *args) bool inherited; Oid locked_table = InvalidOid; - stats_check_required_arg(args, attarginfo, ATTARG_ATTRELSCHEMA); - stats_check_required_arg(args, attarginfo, ATTARG_ATTRELNAME); + 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); @@ -203,7 +203,7 @@ attribute_statistics_update(const NullableDatum *args) errmsg("cannot modify statistics on system column \"%s\"", attname))); - stats_check_required_arg(args, attarginfo, ATTARG_INHERITED); + 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, @@ -255,41 +255,45 @@ attribute_statistics_update_internal(Oid reloid, * and set the corresponding argument to NULL in fcinfo. */ - if (!stats_check_arg_array(args, attarginfo, ATTARG_MOST_COMMON_FREQS)) + if (!stats_check_arg_array(&args[ATTARG_MOST_COMMON_FREQS], attarginfo[ATTARG_MOST_COMMON_FREQS].argname)) { do_mcv = false; result = false; } - if (!stats_check_arg_array(args, attarginfo, ATTARG_MOST_COMMON_ELEM_FREQS)) + if (!stats_check_arg_array(&args[ATTARG_MOST_COMMON_ELEM_FREQS], attarginfo[ATTARG_MOST_COMMON_ELEM_FREQS].argname)) { do_mcelem = false; result = false; } - if (!stats_check_arg_array(args, attarginfo, ATTARG_ELEM_COUNT_HISTOGRAM)) + if (!stats_check_arg_array(&args[ATTARG_ELEM_COUNT_HISTOGRAM], attarginfo[ATTARG_ELEM_COUNT_HISTOGRAM].argname)) { do_dechist = false; result = false; } - if (!stats_check_arg_pair(args, attarginfo, - ATTARG_MOST_COMMON_VALS, ATTARG_MOST_COMMON_FREQS)) + if (!stats_check_arg_pair(&args[ATTARG_MOST_COMMON_VALS], + &args[ATTARG_MOST_COMMON_FREQS], + attarginfo[ATTARG_MOST_COMMON_VALS].argname, + attarginfo[ATTARG_MOST_COMMON_FREQS].argname)) { do_mcv = false; result = false; } - if (!stats_check_arg_pair(args, attarginfo, - ATTARG_MOST_COMMON_ELEMS, - ATTARG_MOST_COMMON_ELEM_FREQS)) + if (!stats_check_arg_pair(&args[ATTARG_MOST_COMMON_ELEMS], + &args[ATTARG_MOST_COMMON_ELEM_FREQS], + attarginfo[ATTARG_MOST_COMMON_ELEMS].argname, + attarginfo[ATTARG_MOST_COMMON_ELEM_FREQS].argname)) { do_mcelem = false; result = false; } - if (!stats_check_arg_pair(args, attarginfo, - ATTARG_RANGE_LENGTH_HISTOGRAM, - ATTARG_RANGE_EMPTY_FRAC)) + if (!stats_check_arg_pair(&args[ATTARG_RANGE_LENGTH_HISTOGRAM], + &args[ATTARG_RANGE_EMPTY_FRAC], + attarginfo[ATTARG_RANGE_LENGTH_HISTOGRAM].argname, + attarginfo[ATTARG_RANGE_EMPTY_FRAC].argname)) { do_range_length_histogram = false; result = false; @@ -625,10 +629,10 @@ pg_clear_attribute_stats(PG_FUNCTION_ARGS) bool inherited; Oid locked_table = InvalidOid; - stats_check_required_arg(fcinfo->args, cleararginfo, C_ATTARG_ATTRELSCHEMA); - stats_check_required_arg(fcinfo->args, cleararginfo, C_ATTARG_ATTRELNAME); - stats_check_required_arg(fcinfo->args, cleararginfo, C_ATTARG_ATTNAME); - stats_check_required_arg(fcinfo->args, cleararginfo, C_ATTARG_INHERITED); + stats_check_required_arg(&fcinfo->args[C_ATTARG_ATTRELSCHEMA], cleararginfo[C_ATTARG_ATTRELSCHEMA].argname); + stats_check_required_arg(&fcinfo->args[C_ATTARG_ATTRELNAME], cleararginfo[C_ATTARG_ATTRELNAME].argname); + stats_check_required_arg(&fcinfo->args[C_ATTARG_ATTNAME], cleararginfo[C_ATTARG_ATTNAME].argname); + stats_check_required_arg(&fcinfo->args[C_ATTARG_INHERITED], cleararginfo[C_ATTARG_INHERITED].argname); nspname = TextDatumGetCString(PG_GETARG_DATUM(C_ATTARG_ATTRELSCHEMA)); relname = TextDatumGetCString(PG_GETARG_DATUM(C_ATTARG_ATTRELNAME)); diff --git a/src/backend/statistics/extended_stats_funcs.c b/src/backend/statistics/extended_stats_funcs.c index 1b730b26c44..0c84160a824 100644 --- a/src/backend/statistics/extended_stats_funcs.c +++ b/src/backend/statistics/extended_stats_funcs.c @@ -375,17 +375,17 @@ extended_statistics_update(const NullableDatum *args) } /* relation arguments */ - stats_check_required_arg(args, extarginfo, EXTARG_RELSCHEMA); + stats_check_required_arg(&args[EXTARG_RELSCHEMA], extarginfo[EXTARG_RELSCHEMA].argname); relnspname = TextDatumGetCString(args[EXTARG_RELSCHEMA].value); - stats_check_required_arg(args, extarginfo, EXTARG_RELNAME); + stats_check_required_arg(&args[EXTARG_RELNAME], extarginfo[EXTARG_RELNAME].argname); relname = TextDatumGetCString(args[EXTARG_RELNAME].value); /* extended statistics arguments */ - stats_check_required_arg(args, extarginfo, EXTARG_STATSCHEMA); + stats_check_required_arg(&args[EXTARG_STATSCHEMA], extarginfo[EXTARG_STATSCHEMA].argname); nspname = TextDatumGetCString(args[EXTARG_STATSCHEMA].value); - stats_check_required_arg(args, extarginfo, EXTARG_STATNAME); + stats_check_required_arg(&args[EXTARG_STATNAME], extarginfo[EXTARG_STATNAME].argname); stxname = TextDatumGetCString(args[EXTARG_STATNAME].value); - stats_check_required_arg(args, extarginfo, EXTARG_INHERITED); + stats_check_required_arg(&args[EXTARG_INHERITED], extarginfo[EXTARG_INHERITED].argname); inherited = DatumGetBool(args[EXTARG_INHERITED].value); /* @@ -1757,17 +1757,17 @@ pg_clear_extended_stats(PG_FUNCTION_ARGS) Oid locked_table = InvalidOid; /* relation arguments */ - stats_check_required_arg(fcinfo->args, extarginfo, EXTARG_RELSCHEMA); + stats_check_required_arg(&fcinfo->args[EXTARG_RELSCHEMA], extarginfo[EXTARG_RELSCHEMA].argname); relnspname = TextDatumGetCString(PG_GETARG_DATUM(EXTARG_RELSCHEMA)); - stats_check_required_arg(fcinfo->args, extarginfo, EXTARG_RELNAME); + stats_check_required_arg(&fcinfo->args[EXTARG_RELNAME], extarginfo[EXTARG_RELNAME].argname); relname = TextDatumGetCString(PG_GETARG_DATUM(EXTARG_RELNAME)); /* extended statistics arguments */ - stats_check_required_arg(fcinfo->args, extarginfo, EXTARG_STATSCHEMA); + stats_check_required_arg(&fcinfo->args[EXTARG_STATSCHEMA], extarginfo[EXTARG_STATSCHEMA].argname); nspname = TextDatumGetCString(PG_GETARG_DATUM(EXTARG_STATSCHEMA)); - stats_check_required_arg(fcinfo->args, extarginfo, EXTARG_STATNAME); + stats_check_required_arg(&fcinfo->args[EXTARG_STATNAME], extarginfo[EXTARG_STATNAME].argname); stxname = TextDatumGetCString(PG_GETARG_DATUM(EXTARG_STATNAME)); - stats_check_required_arg(fcinfo->args, extarginfo, EXTARG_INHERITED); + stats_check_required_arg(&fcinfo->args[EXTARG_INHERITED], extarginfo[EXTARG_INHERITED].argname); inherited = PG_GETARG_BOOL(EXTARG_INHERITED); if (RecoveryInProgress()) diff --git a/src/backend/statistics/relation_stats.c b/src/backend/statistics/relation_stats.c index eaf7a1e326b..2e62cf5b9e3 100644 --- a/src/backend/statistics/relation_stats.c +++ b/src/backend/statistics/relation_stats.c @@ -76,8 +76,8 @@ relation_statistics_update(const NullableDatum *args) Oid reloid; Oid locked_table = InvalidOid; - stats_check_required_arg(args, relarginfo, RELARG_SCHEMA); - stats_check_required_arg(args, relarginfo, RELARG_RELNAME); + stats_check_required_arg(&args[RELARG_SCHEMA], relarginfo[RELARG_SCHEMA].argname); + stats_check_required_arg(&args[RELARG_RELNAME], relarginfo[RELARG_RELNAME].argname); nspname = TextDatumGetCString(args[RELARG_SCHEMA].value); relname = TextDatumGetCString(args[RELARG_RELNAME].value); diff --git a/src/backend/statistics/stat_utils.c b/src/backend/statistics/stat_utils.c index 29655d55339..f4d238c5ce0 100644 --- a/src/backend/statistics/stat_utils.c +++ b/src/backend/statistics/stat_utils.c @@ -51,15 +51,15 @@ static Node *statatt_get_index_expr(Relation rel, int attnum); * Ensure that a given argument is not null. */ void -stats_check_required_arg(const NullableDatum *args, - struct StatsArgInfo *arginfo, - int argnum) +stats_check_required_arg(const NullableDatum *arg, + const char *argname) { - if (args[argnum].isnull) + Assert(arg); + + if (arg->isnull) ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("argument \"%s\" must not be null", - arginfo[argnum].argname))); + errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("argument \"%s\" must not be null", argname)); } /* @@ -70,32 +70,33 @@ 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) + Assert(arg); + + 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))); + errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("argument \"%s\" must not be a multidimensional array", + argname)); return false; } if (array_contains_nulls(arr)) { ereport(WARNING, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("argument \"%s\" array must not contain null values", - arginfo[argnum].argname))); + errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("argument \"%s\" array must not contain null values", + argname)); return false; } @@ -111,23 +112,23 @@ 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) - return true; + Assert(arg1); + Assert(arg2); - 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 *nullargname = arg1->isnull ? argname1 : argname2; + const char *otherargname = 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))); + errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("argument \"%s\" must be specified when argument \"%s\" is specified", + nullargname, otherargname)); return false; } diff --git a/src/include/statistics/stat_utils.h b/src/include/statistics/stat_utils.h index 39027a4ab03..4bdf7275425 100644 --- a/src/include/statistics/stat_utils.h +++ b/src/include/statistics/stat_utils.h @@ -26,14 +26,13 @@ struct StatsArgInfo Oid argtype; }; -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 void stats_check_required_arg(const NullableDatum *arg, + const char *argname); +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); -- 2.50.1 (Apple Git-155)