From ec6fa973b0bb6b3a422df1380ebae2432824a739 Mon Sep 17 00:00:00 2001 From: Corey Huinker Date: Sun, 28 Jun 2026 17:21:51 -0500 Subject: [PATCH v1 3/5] Change stats_fill_fcinfo_from_arg_pairs to NullableDatum array. Change stats_fill_fcinfo_from_arg_pairs to NullableDatum array, and in doing so rename to stats_fill_args_from_arg_pairs. Change all callers to instead initialize an NullableDatum array of the proper size instead of a full FunctionCallInfoData structure. --- src/backend/statistics/attribute_stats.c | 91 ++++++++----------- src/backend/statistics/extended_stats_funcs.c | 11 +-- src/backend/statistics/relation_stats.c | 85 ++++++++--------- src/backend/statistics/stat_utils.c | 24 ++--- src/include/statistics/stat_utils.h | 6 +- 5 files changed, 95 insertions(+), 122 deletions(-) diff --git a/src/backend/statistics/attribute_stats.c b/src/backend/statistics/attribute_stats.c index a50d60223c9..e7ee0b3443f 100644 --- a/src/backend/statistics/attribute_stats.c +++ b/src/backend/statistics/attribute_stats.c @@ -104,7 +104,7 @@ static struct StatsArgInfo cleararginfo[] = [C_NUM_ATTRIBUTE_STATS_ARGS] = {0} }; -static bool attribute_statistics_update(FunctionCallInfo fcinfo); +static bool attribute_statistics_update(const NullableDatum *args); static bool attribute_statistics_update_internal(Oid reloid, const char *attname, AttrNumber attnum, @@ -131,7 +131,7 @@ static bool delete_pg_statistic(Oid reloid, AttrNumber attnum, bool stainherit); * and other statistic kinds may still be updated. */ static bool -attribute_statistics_update(FunctionCallInfo fcinfo) +attribute_statistics_update(const NullableDatum *args) { char *nspname; char *relname; @@ -141,11 +141,11 @@ attribute_statistics_update(FunctionCallInfo fcinfo) bool inherited; Oid locked_table = InvalidOid; - stats_check_required_arg(fcinfo->args, attarginfo, ATTRELSCHEMA_ARG); - stats_check_required_arg(fcinfo->args, attarginfo, ATTRELNAME_ARG); + stats_check_required_arg(args, attarginfo, ATTRELSCHEMA_ARG); + stats_check_required_arg(args, attarginfo, ATTRELNAME_ARG); - nspname = TextDatumGetCString(PG_GETARG_DATUM(ATTRELSCHEMA_ARG)); - relname = TextDatumGetCString(PG_GETARG_DATUM(ATTRELNAME_ARG)); + nspname = TextDatumGetCString(args[ATTRELSCHEMA_ARG].value); + relname = TextDatumGetCString(args[ATTRELNAME_ARG].value); if (RecoveryInProgress()) ereport(ERROR, @@ -159,13 +159,13 @@ attribute_statistics_update(FunctionCallInfo fcinfo) RangeVarCallbackForStats, &locked_table); /* user can specify either attname or attnum, but not both */ - if (!PG_ARGISNULL(ATTNAME_ARG)) + if (!args[ATTNAME_ARG].isnull) { - if (!PG_ARGISNULL(ATTNUM_ARG)) + if (!args[ATTNUM_ARG].isnull) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("cannot specify both \"%s\" and \"%s\"", "attname", "attnum"))); - attname = TextDatumGetCString(PG_GETARG_DATUM(ATTNAME_ARG)); + attname = TextDatumGetCString(args[ATTNAME_ARG].value); attnum = get_attnum(reloid, attname); /* note that this test covers attisdropped cases too: */ if (attnum == InvalidAttrNumber) @@ -174,9 +174,9 @@ attribute_statistics_update(FunctionCallInfo fcinfo) errmsg("column \"%s\" of relation \"%s\" does not exist", attname, relname))); } - else if (!PG_ARGISNULL(ATTNUM_ARG)) + else if (!args[ATTNUM_ARG].isnull) { - attnum = PG_GETARG_INT16(ATTNUM_ARG); + attnum = DatumGetInt16(args[ATTNUM_ARG].value); attname = get_attname(reloid, attnum, true); /* annoyingly, get_attname doesn't check attisdropped */ if (attname == NULL || @@ -201,11 +201,11 @@ attribute_statistics_update(FunctionCallInfo fcinfo) errmsg("cannot modify statistics on system column \"%s\"", attname))); - stats_check_required_arg(fcinfo->args, attarginfo, INHERITED_ARG); - inherited = PG_GETARG_BOOL(INHERITED_ARG); + stats_check_required_arg(args, attarginfo, INHERITED_ARG); + inherited = DatumGetBool(args[INHERITED_ARG].value); return attribute_statistics_update_internal(reloid, attname, attnum, - inherited, fcinfo->args); + inherited, args); } /* @@ -698,17 +698,14 @@ pg_clear_attribute_stats(PG_FUNCTION_ARGS) Datum pg_restore_attribute_stats(PG_FUNCTION_ARGS) { - LOCAL_FCINFO(positional_fcinfo, NUM_ATTRIBUTE_STATS_ARGS); + NullableDatum positional_args[NUM_ATTRIBUTE_STATS_ARGS]; bool result = true; - InitFunctionCallInfoData(*positional_fcinfo, NULL, NUM_ATTRIBUTE_STATS_ARGS, - InvalidOid, NULL, NULL); - - if (!stats_fill_fcinfo_from_arg_pairs(fcinfo, positional_fcinfo, - attarginfo)) + if (!stats_fill_args_from_arg_pairs(fcinfo, positional_args, + attarginfo)) result = false; - if (!attribute_statistics_update(positional_fcinfo)) + if (!attribute_statistics_update(positional_args)) result = false; PG_RETURN_BOOL(result); @@ -738,10 +735,11 @@ import_attribute_statistics(Relation rel, AttrNumber attnum, bool inherited, const NullableDatum *range_empty_frac, const NullableDatum *range_bounds_histogram) { - LOCAL_FCINFO(newfcinfo, NUM_ATTRIBUTE_STATS_ARGS); + 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); @@ -765,37 +763,28 @@ import_attribute_statistics(Relation rel, AttrNumber attnum, bool inherited, errmsg("column %d of relation \"%s\" does not exist", attnum, relname))); - InitFunctionCallInfoData(*newfcinfo, NULL, NUM_ATTRIBUTE_STATS_ARGS, - InvalidOid, NULL, NULL); - - newfcinfo->args[ATTRELSCHEMA_ARG].value = - CStringGetTextDatum(get_namespace_name(RelationGetNamespace(rel))); - newfcinfo->args[ATTRELSCHEMA_ARG].isnull = false; - newfcinfo->args[ATTRELNAME_ARG].value = CStringGetTextDatum(relname); - newfcinfo->args[ATTRELNAME_ARG].isnull = false; - newfcinfo->args[ATTNAME_ARG].value = CStringGetTextDatum(attname); - newfcinfo->args[ATTNAME_ARG].isnull = false; - newfcinfo->args[ATTNUM_ARG].value = Int16GetDatum(attnum); - newfcinfo->args[ATTNUM_ARG].isnull = false; - newfcinfo->args[INHERITED_ARG].value = BoolGetDatum(inherited); - newfcinfo->args[INHERITED_ARG].isnull = false; - - newfcinfo->args[NULL_FRAC_ARG] = *null_frac; - newfcinfo->args[AVG_WIDTH_ARG] = *avg_width; - newfcinfo->args[N_DISTINCT_ARG] = *n_distinct; - newfcinfo->args[MOST_COMMON_VALS_ARG] = *most_common_vals; - newfcinfo->args[MOST_COMMON_FREQS_ARG] = *most_common_freqs; - newfcinfo->args[HISTOGRAM_BOUNDS_ARG] = *histogram_bounds; - newfcinfo->args[CORRELATION_ARG] = *correlation; - newfcinfo->args[MOST_COMMON_ELEMS_ARG] = *most_common_elems; - newfcinfo->args[MOST_COMMON_ELEM_FREQS_ARG] = *most_common_elem_freqs; - newfcinfo->args[ELEM_COUNT_HISTOGRAM_ARG] = *elem_count_histogram; - newfcinfo->args[RANGE_LENGTH_HISTOGRAM_ARG] = *range_length_histogram; - newfcinfo->args[RANGE_EMPTY_FRAC_ARG] = *range_empty_frac; - newfcinfo->args[RANGE_BOUNDS_HISTOGRAM_ARG] = *range_bounds_histogram; + 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, newfcinfo->args); + inherited, args); } /* diff --git a/src/backend/statistics/extended_stats_funcs.c b/src/backend/statistics/extended_stats_funcs.c index b479c49c85e..96591e79c72 100644 --- a/src/backend/statistics/extended_stats_funcs.c +++ b/src/backend/statistics/extended_stats_funcs.c @@ -1718,22 +1718,19 @@ delete_pg_statistic_ext_data(Oid stxoid, bool inherited) * Restore (insert or replace) statistics for the given statistics object. * * This function accepts variadic arguments in key-value pairs, which are - * given to stats_fill_fcinfo_from_arg_pairs to be mapped into positional + * given to stats_fill_args_from_arg_pairs to be mapped into positional * arguments. */ Datum pg_restore_extended_stats(PG_FUNCTION_ARGS) { - LOCAL_FCINFO(positional_fcinfo, NUM_EXTENDED_STATS_ARGS); + NullableDatum positional_args[NUM_EXTENDED_STATS_ARGS]; bool result = true; - InitFunctionCallInfoData(*positional_fcinfo, NULL, NUM_EXTENDED_STATS_ARGS, - InvalidOid, NULL, NULL); - - if (!stats_fill_fcinfo_from_arg_pairs(fcinfo, positional_fcinfo, extarginfo)) + if (!stats_fill_args_from_arg_pairs(fcinfo, positional_args, extarginfo)) result = false; - if (!extended_statistics_update(positional_fcinfo->args)) + if (!extended_statistics_update(positional_args)) result = false; PG_RETURN_BOOL(result); diff --git a/src/backend/statistics/relation_stats.c b/src/backend/statistics/relation_stats.c index 6ec3f4d068d..392aeed5d25 100644 --- a/src/backend/statistics/relation_stats.c +++ b/src/backend/statistics/relation_stats.c @@ -59,7 +59,7 @@ static struct StatsArgInfo relarginfo[] = [NUM_RELATION_STATS_ARGS] = {0} }; -static bool relation_statistics_update(FunctionCallInfo fcinfo); +static bool relation_statistics_update(const NullableDatum *args); static bool relation_statistics_update_internal(Oid reloid, const NullableDatum *args); @@ -67,18 +67,18 @@ static bool relation_statistics_update_internal(Oid reloid, * Internal function for modifying statistics for a relation. */ static bool -relation_statistics_update(FunctionCallInfo fcinfo) +relation_statistics_update(const NullableDatum *args) { char *nspname; char *relname; Oid reloid; Oid locked_table = InvalidOid; - stats_check_required_arg(fcinfo->args, relarginfo, RELSCHEMA_ARG); - stats_check_required_arg(fcinfo->args, relarginfo, RELNAME_ARG); + stats_check_required_arg(args, relarginfo, RELSCHEMA_ARG); + stats_check_required_arg(args, relarginfo, RELNAME_ARG); - nspname = TextDatumGetCString(PG_GETARG_DATUM(RELSCHEMA_ARG)); - relname = TextDatumGetCString(PG_GETARG_DATUM(RELNAME_ARG)); + nspname = TextDatumGetCString(args[RELSCHEMA_ARG].value); + relname = TextDatumGetCString(args[RELNAME_ARG].value); if (RecoveryInProgress()) ereport(ERROR, @@ -90,7 +90,7 @@ relation_statistics_update(FunctionCallInfo fcinfo) ShareUpdateExclusiveLock, 0, RangeVarCallbackForStats, &locked_table); - return relation_statistics_update_internal(reloid, fcinfo->args); + return relation_statistics_update_internal(reloid, args); } /* @@ -223,42 +223,36 @@ relation_statistics_update_internal(Oid reloid, const NullableDatum *args) Datum pg_clear_relation_stats(PG_FUNCTION_ARGS) { - LOCAL_FCINFO(newfcinfo, 6); - - InitFunctionCallInfoData(*newfcinfo, NULL, 6, InvalidOid, NULL, NULL); - - newfcinfo->args[0].value = PG_GETARG_DATUM(0); - newfcinfo->args[0].isnull = PG_ARGISNULL(0); - newfcinfo->args[1].value = PG_GETARG_DATUM(1); - newfcinfo->args[1].isnull = PG_ARGISNULL(1); - newfcinfo->args[2].value = Int32GetDatum(0); - newfcinfo->args[2].isnull = false; - newfcinfo->args[3].value = Float4GetDatum(-1.0); - newfcinfo->args[3].isnull = false; - newfcinfo->args[4].value = Int32GetDatum(0); - newfcinfo->args[4].isnull = false; - newfcinfo->args[5].value = Int32GetDatum(0); - newfcinfo->args[5].isnull = false; - - relation_statistics_update(newfcinfo); + NullableDatum args[NUM_RELATION_STATS_ARGS]; + + args[RELSCHEMA_ARG].value = PG_GETARG_DATUM(0); + args[RELSCHEMA_ARG].isnull = PG_ARGISNULL(0); + args[RELNAME_ARG].value = PG_GETARG_DATUM(1); + args[RELNAME_ARG].isnull = PG_ARGISNULL(1); + args[RELPAGES_ARG].value = Int32GetDatum(0); + args[RELPAGES_ARG].isnull = false; + args[RELTUPLES_ARG].value = Float4GetDatum(-1.0); + args[RELTUPLES_ARG].isnull = false; + args[RELALLVISIBLE_ARG].value = Int32GetDatum(0); + args[RELALLVISIBLE_ARG].isnull = false; + args[RELALLFROZEN_ARG].value = Int32GetDatum(0); + args[RELALLFROZEN_ARG].isnull = false; + + relation_statistics_update(args); PG_RETURN_VOID(); } Datum pg_restore_relation_stats(PG_FUNCTION_ARGS) { - LOCAL_FCINFO(positional_fcinfo, NUM_RELATION_STATS_ARGS); + NullableDatum positional_args[NUM_RELATION_STATS_ARGS]; bool result = true; - InitFunctionCallInfoData(*positional_fcinfo, NULL, - NUM_RELATION_STATS_ARGS, - InvalidOid, NULL, NULL); - - if (!stats_fill_fcinfo_from_arg_pairs(fcinfo, positional_fcinfo, - relarginfo)) + if (!stats_fill_args_from_arg_pairs(fcinfo, positional_args, + relarginfo)) result = false; - if (!relation_statistics_update(positional_fcinfo)) + if (!relation_statistics_update(positional_args)) result = false; PG_RETURN_BOOL(result); @@ -279,28 +273,21 @@ import_relation_statistics(Relation rel, const NullableDatum *relallvisible, const NullableDatum *relallfrozen) { - LOCAL_FCINFO(newfcinfo, NUM_RELATION_STATS_ARGS); + NullableDatum args[NUM_RELATION_STATS_ARGS]; + NullableDatum unused = {.isnull = true, .value = (Datum) 0}; Assert(relpages); Assert(reltuples); Assert(relallvisible); Assert(relallfrozen); - InitFunctionCallInfoData(*newfcinfo, NULL, NUM_RELATION_STATS_ARGS, - InvalidOid, NULL, NULL); - - newfcinfo->args[RELSCHEMA_ARG].value = - CStringGetTextDatum(get_namespace_name(RelationGetNamespace(rel))); - newfcinfo->args[RELSCHEMA_ARG].isnull = false; - newfcinfo->args[RELNAME_ARG].value = - CStringGetTextDatum(RelationGetRelationName(rel)); - newfcinfo->args[RELNAME_ARG].isnull = false; + args[RELSCHEMA_ARG] = unused; + args[RELNAME_ARG] = unused; - newfcinfo->args[RELPAGES_ARG] = *relpages; - newfcinfo->args[RELTUPLES_ARG] = *reltuples; - newfcinfo->args[RELALLVISIBLE_ARG] = *relallvisible; - newfcinfo->args[RELALLFROZEN_ARG] = *relallfrozen; + args[RELPAGES_ARG] = *relpages; + args[RELTUPLES_ARG] = *reltuples; + args[RELALLVISIBLE_ARG] = *relallvisible; + args[RELALLFROZEN_ARG] = *relallfrozen; - return relation_statistics_update_internal(RelationGetRelid(rel), - newfcinfo->args); + return relation_statistics_update_internal(RelationGetRelid(rel), args); } diff --git a/src/backend/statistics/stat_utils.c b/src/backend/statistics/stat_utils.c index c1698497d68..4befc887cd2 100644 --- a/src/backend/statistics/stat_utils.c +++ b/src/backend/statistics/stat_utils.c @@ -340,17 +340,17 @@ statatt_get_index_expr(Relation rel, int attnum) /* * Translate variadic argument pairs from 'pairs_fcinfo' into a - * 'positional_fcinfo' appropriate for calling relation_statistics_update() or - * attribute_statistics_update() with positional arguments. + * NullableDatum[] appropriate for calling the internal statistics update + * functions for relation stats, attribute stats, or extended stats. * - * Caller should have already initialized positional_fcinfo with a size - * appropriate for calling the intended positional function, and arginfo - * should also match the intended positional function. + * Caller should have already initialized args with a size appropriate for + * calling the intended function, and arginfo should also match the intended + * function. */ bool -stats_fill_fcinfo_from_arg_pairs(FunctionCallInfo pairs_fcinfo, - FunctionCallInfo positional_fcinfo, - struct StatsArgInfo *arginfo) +stats_fill_args_from_arg_pairs(FunctionCallInfo pairs_fcinfo, + NullableDatum *positional_args, + struct StatsArgInfo *arginfo) { Datum *args; bool *argnulls; @@ -361,8 +361,8 @@ stats_fill_fcinfo_from_arg_pairs(FunctionCallInfo pairs_fcinfo, /* clear positional args */ for (int i = 0; arginfo[i].argname != NULL; i++) { - positional_fcinfo->args[i].value = (Datum) 0; - positional_fcinfo->args[i].isnull = true; + positional_args[i].value = (Datum) 0; + positional_args[i].isnull = true; } nargs = extract_variadic_args(pairs_fcinfo, 0, true, @@ -417,8 +417,8 @@ stats_fill_fcinfo_from_arg_pairs(FunctionCallInfo pairs_fcinfo, continue; } - positional_fcinfo->args[argnum].value = args[i + 1]; - positional_fcinfo->args[argnum].isnull = false; + positional_args[argnum].value = args[i + 1]; + positional_args[argnum].isnull = false; } return result; diff --git a/src/include/statistics/stat_utils.h b/src/include/statistics/stat_utils.h index 8209c0d8949..0560826fcfe 100644 --- a/src/include/statistics/stat_utils.h +++ b/src/include/statistics/stat_utils.h @@ -37,9 +37,9 @@ extern bool stats_check_arg_pair(const NullableDatum *args, extern void RangeVarCallbackForStats(const RangeVar *relation, Oid relId, Oid oldRelId, void *arg); -extern bool stats_fill_fcinfo_from_arg_pairs(FunctionCallInfo pairs_fcinfo, - FunctionCallInfo positional_fcinfo, - struct StatsArgInfo *arginfo); +extern bool stats_fill_args_from_arg_pairs(FunctionCallInfo pairs_fcinfo, + NullableDatum *positional_args, + struct StatsArgInfo *arginfo); extern void statatt_get_type(Oid reloid, AttrNumber attnum, Oid *atttypid, int32 *atttypmod, -- 2.50.1 (Apple Git-155)