diff --git a/contrib/postgres_fdw/postgres_fdw.c b/contrib/postgres_fdw/postgres_fdw.c index 9269418a074..2cc594aecb6 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/backend/statistics/attribute_stats.c b/src/backend/statistics/attribute_stats.c index c35892ce6d0..1d19827dc45 100644 --- a/src/backend/statistics/attribute_stats.c +++ b/src/backend/statistics/attribute_stats.c @@ -104,12 +104,12 @@ 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, bool inherited, - FunctionCallInfo fcinfo); + 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); @@ -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; @@ -140,12 +140,13 @@ attribute_statistics_update(FunctionCallInfo fcinfo) AttrNumber attnum; bool inherited; Oid locked_table = InvalidOid; + AttributeStatsValues values; - stats_check_required_arg(fcinfo, attarginfo, ATTRELSCHEMA_ARG); - stats_check_required_arg(fcinfo, 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 +160,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 +175,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 +202,28 @@ attribute_statistics_update(FunctionCallInfo fcinfo) errmsg("cannot modify statistics on system column \"%s\"", attname))); - stats_check_required_arg(fcinfo, attarginfo, INHERITED_ARG); - inherited = PG_GETARG_BOOL(INHERITED_ARG); + 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, fcinfo); + inherited, &values); } /* @@ -214,7 +232,8 @@ attribute_statistics_update(FunctionCallInfo fcinfo) static bool attribute_statistics_update_internal(Oid reloid, const char *attname, AttrNumber attnum, - bool inherited, FunctionCallInfo fcinfo) + 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 = !PG_ARGISNULL(MOST_COMMON_FREQS_ARG) && - !PG_ARGISNULL(MOST_COMMON_VALS_ARG); - bool do_histogram = !PG_ARGISNULL(HISTOGRAM_BOUNDS_ARG); - bool do_correlation = !PG_ARGISNULL(CORRELATION_ARG); - bool do_mcelem = !PG_ARGISNULL(MOST_COMMON_ELEMS_ARG) && - !PG_ARGISNULL(MOST_COMMON_ELEM_FREQS_ARG); - bool do_dechist = !PG_ARGISNULL(ELEM_COUNT_HISTOGRAM_ARG); - bool do_bounds_histogram = !PG_ARGISNULL(RANGE_BOUNDS_HISTOGRAM_ARG); - bool do_range_length_histogram = !PG_ARGISNULL(RANGE_LENGTH_HISTOGRAM_ARG) && - !PG_ARGISNULL(RANGE_EMPTY_FRAC_ARG); + 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(fcinfo, 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(fcinfo, 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(fcinfo, 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(fcinfo, 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(fcinfo, 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(fcinfo, 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 (!PG_ARGISNULL(NULL_FRAC_ARG)) + if (!statvalues->null_frac.isnull) { - values[Anum_pg_statistic_stanullfrac - 1] = PG_GETARG_DATUM(NULL_FRAC_ARG); + values[Anum_pg_statistic_stanullfrac - 1] = statvalues->null_frac.value; replaces[Anum_pg_statistic_stanullfrac - 1] = true; } - if (!PG_ARGISNULL(AVG_WIDTH_ARG)) + if (!statvalues->avg_width.isnull) { - values[Anum_pg_statistic_stawidth - 1] = PG_GETARG_DATUM(AVG_WIDTH_ARG); + values[Anum_pg_statistic_stawidth - 1] = statvalues->avg_width.value; replaces[Anum_pg_statistic_stawidth - 1] = true; } - if (!PG_ARGISNULL(N_DISTINCT_ARG)) + if (!statvalues->n_distinct.isnull) { - values[Anum_pg_statistic_stadistinct - 1] = PG_GETARG_DATUM(N_DISTINCT_ARG); + 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 = PG_GETARG_DATUM(MOST_COMMON_FREQS_ARG); + Datum stanumbers = statvalues->most_common_freqs.value; Datum stavalues = statatt_build_stavalues("most_common_vals", &array_in_fn, - PG_GETARG_DATUM(MOST_COMMON_VALS_ARG), + 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, - PG_GETARG_DATUM(HISTOGRAM_BOUNDS_ARG), + 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[] = {PG_GETARG_DATUM(CORRELATION_ARG)}; + 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 = PG_GETARG_DATUM(MOST_COMMON_ELEM_FREQS_ARG); + Datum stanumbers = statvalues->most_common_elem_freqs.value; bool converted = false; Datum stavalues; stavalues = statatt_build_stavalues("most_common_elems", &array_in_fn, - PG_GETARG_DATUM(MOST_COMMON_ELEMS_ARG), + 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 = PG_GETARG_DATUM(ELEM_COUNT_HISTOGRAM_ARG); + 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, - PG_GETARG_DATUM(RANGE_BOUNDS_HISTOGRAM_ARG), + 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[] = {PG_GETARG_DATUM(RANGE_EMPTY_FRAC_ARG)}; + 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, - PG_GETARG_DATUM(RANGE_LENGTH_HISTOGRAM_ARG), + statvalues->range_length_histogram.value, FLOAT8OID, 0, &converted); if (converted) @@ -631,10 +654,10 @@ pg_clear_attribute_stats(PG_FUNCTION_ARGS) bool inherited; Oid locked_table = InvalidOid; - stats_check_required_arg(fcinfo, cleararginfo, C_ATTRELSCHEMA_ARG); - stats_check_required_arg(fcinfo, cleararginfo, C_ATTRELNAME_ARG); - stats_check_required_arg(fcinfo, cleararginfo, C_ATTNAME_ARG); - stats_check_required_arg(fcinfo, cleararginfo, C_INHERITED_ARG); + stats_check_required_arg(fcinfo->args, cleararginfo, C_ATTRELSCHEMA_ARG); + stats_check_required_arg(fcinfo->args, cleararginfo, C_ATTRELNAME_ARG); + stats_check_required_arg(fcinfo->args, cleararginfo, C_ATTNAME_ARG); + stats_check_required_arg(fcinfo->args, cleararginfo, C_INHERITED_ARG); nspname = TextDatumGetCString(PG_GETARG_DATUM(C_ATTRELSCHEMA_ARG)); relname = TextDatumGetCString(PG_GETARG_DATUM(C_ATTRELNAME_ARG)); @@ -699,64 +722,33 @@ 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); } /* - * 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) { - LOCAL_FCINFO(newfcinfo, NUM_ATTRIBUTE_STATS_ARGS); Oid reloid = RelationGetRelid(rel); char *relname = RelationGetRelationName(rel); char *attname = get_attname(reloid, attnum, true); - 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 || @@ -766,37 +758,8 @@ 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; - return attribute_statistics_update_internal(reloid, attname, attnum, - inherited, newfcinfo); + inherited, statvalues); } /* diff --git a/src/backend/statistics/extended_stats_funcs.c b/src/backend/statistics/extended_stats_funcs.c index cb965fdb868..6bd41254221 100644 --- a/src/backend/statistics/extended_stats_funcs.c +++ b/src/backend/statistics/extended_stats_funcs.c @@ -121,7 +121,7 @@ static const char *extexprargname[NUM_ATTRIBUTE_STATS_ELEMS] = "range_bounds_histogram" }; -static bool extended_statistics_update(FunctionCallInfo fcinfo); +static bool extended_statistics_update(const NullableDatum *args); static HeapTuple get_pg_statistic_ext(Relation pg_stext, Oid nspoid, const char *stxname); @@ -311,7 +311,7 @@ upsert_pg_statistic_ext_data(const Datum *values, const bool *nulls, * be updated. */ static bool -extended_statistics_update(FunctionCallInfo fcinfo) +extended_statistics_update(const NullableDatum *args) { char *relnspname; char *relname; @@ -356,12 +356,12 @@ extended_statistics_update(FunctionCallInfo fcinfo) * Therefore, none of the three array values is meaningful unless the * other two are also present and in sync in terms of array length. */ - has.mcv = (!PG_ARGISNULL(MOST_COMMON_VALS_ARG) && - !PG_ARGISNULL(MOST_COMMON_FREQS_ARG) && - !PG_ARGISNULL(MOST_COMMON_BASE_FREQS_ARG)); - has.ndistinct = !PG_ARGISNULL(NDISTINCT_ARG); - has.dependencies = !PG_ARGISNULL(DEPENDENCIES_ARG); - has.expressions = !PG_ARGISNULL(EXPRESSIONS_ARG); + has.mcv = (!args[MOST_COMMON_VALS_ARG].isnull && + !args[MOST_COMMON_FREQS_ARG].isnull && + !args[MOST_COMMON_BASE_FREQS_ARG].isnull); + has.ndistinct = !args[NDISTINCT_ARG].isnull; + has.dependencies = !args[DEPENDENCIES_ARG].isnull; + has.expressions = !args[EXPRESSIONS_ARG].isnull; if (RecoveryInProgress()) { @@ -373,18 +373,18 @@ extended_statistics_update(FunctionCallInfo fcinfo) } /* relation arguments */ - stats_check_required_arg(fcinfo, extarginfo, RELSCHEMA_ARG); - relnspname = TextDatumGetCString(PG_GETARG_DATUM(RELSCHEMA_ARG)); - stats_check_required_arg(fcinfo, extarginfo, RELNAME_ARG); - relname = TextDatumGetCString(PG_GETARG_DATUM(RELNAME_ARG)); + stats_check_required_arg(args, extarginfo, RELSCHEMA_ARG); + relnspname = TextDatumGetCString(args[RELSCHEMA_ARG].value); + stats_check_required_arg(args, extarginfo, RELNAME_ARG); + relname = TextDatumGetCString(args[RELNAME_ARG].value); /* extended statistics arguments */ - stats_check_required_arg(fcinfo, extarginfo, STATSCHEMA_ARG); - nspname = TextDatumGetCString(PG_GETARG_DATUM(STATSCHEMA_ARG)); - stats_check_required_arg(fcinfo, extarginfo, STATNAME_ARG); - stxname = TextDatumGetCString(PG_GETARG_DATUM(STATNAME_ARG)); - stats_check_required_arg(fcinfo, extarginfo, INHERITED_ARG); - inherited = PG_GETARG_BOOL(INHERITED_ARG); + stats_check_required_arg(args, extarginfo, STATSCHEMA_ARG); + nspname = TextDatumGetCString(args[STATSCHEMA_ARG].value); + stats_check_required_arg(args, extarginfo, STATNAME_ARG); + stxname = TextDatumGetCString(args[STATNAME_ARG].value); + stats_check_required_arg(args, extarginfo, INHERITED_ARG); + inherited = DatumGetBool(args[INHERITED_ARG].value); /* * First open the relation where we expect to find the statistics. This @@ -514,9 +514,9 @@ extended_statistics_update(FunctionCallInfo fcinfo) */ if (!enabled.mcv) { - if (!PG_ARGISNULL(MOST_COMMON_VALS_ARG) || - !PG_ARGISNULL(MOST_COMMON_FREQS_ARG) || - !PG_ARGISNULL(MOST_COMMON_BASE_FREQS_ARG)) + if (!args[MOST_COMMON_VALS_ARG].isnull || + !args[MOST_COMMON_FREQS_ARG].isnull || + !args[MOST_COMMON_BASE_FREQS_ARG].isnull) { ereport(WARNING, errcode(ERRCODE_INVALID_PARAMETER_VALUE), @@ -538,9 +538,9 @@ extended_statistics_update(FunctionCallInfo fcinfo) * statistics object expects something, something is wrong. This * issues a WARNING if a partial input has been provided. */ - if (!PG_ARGISNULL(MOST_COMMON_VALS_ARG) || - !PG_ARGISNULL(MOST_COMMON_FREQS_ARG) || - !PG_ARGISNULL(MOST_COMMON_BASE_FREQS_ARG)) + if (!args[MOST_COMMON_VALS_ARG].isnull || + !args[MOST_COMMON_FREQS_ARG].isnull || + !args[MOST_COMMON_BASE_FREQS_ARG].isnull) { ereport(WARNING, errcode(ERRCODE_INVALID_PARAMETER_VALUE), @@ -655,7 +655,7 @@ extended_statistics_update(FunctionCallInfo fcinfo) if (has.ndistinct) { - Datum ndistinct_datum = PG_GETARG_DATUM(NDISTINCT_ARG); + Datum ndistinct_datum = args[NDISTINCT_ARG].value; bytea *data = DatumGetByteaPP(ndistinct_datum); MVNDistinct *ndistinct = statext_ndistinct_deserialize(data); @@ -674,7 +674,7 @@ extended_statistics_update(FunctionCallInfo fcinfo) if (has.dependencies) { - Datum dependencies_datum = PG_GETARG_DATUM(DEPENDENCIES_ARG); + Datum dependencies_datum = args[DEPENDENCIES_ARG].value; bytea *data = DatumGetByteaPP(dependencies_datum); MVDependencies *dependencies = statext_dependencies_deserialize(data); @@ -696,9 +696,9 @@ extended_statistics_update(FunctionCallInfo fcinfo) Datum datum; bool val_ok = false; - datum = import_mcv(PG_GETARG_ARRAYTYPE_P(MOST_COMMON_VALS_ARG), - PG_GETARG_ARRAYTYPE_P(MOST_COMMON_FREQS_ARG), - PG_GETARG_ARRAYTYPE_P(MOST_COMMON_BASE_FREQS_ARG), + datum = import_mcv(DatumGetArrayTypeP(args[MOST_COMMON_VALS_ARG].value), + DatumGetArrayTypeP(args[MOST_COMMON_FREQS_ARG].value), + DatumGetArrayTypeP(args[MOST_COMMON_BASE_FREQS_ARG].value), atttypids, atttypmods, atttypcolls, numattrs, &val_ok); @@ -733,7 +733,7 @@ extended_statistics_update(FunctionCallInfo fcinfo) &atttypids[numattnums], &atttypmods[numattnums], &atttypcolls[numattnums], - PG_GETARG_JSONB_P(EXPRESSIONS_ARG), + DatumGetJsonbP(args[EXPRESSIONS_ARG].value), &ok); table_close(pgsd, RowExclusiveLock); @@ -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)) + if (!extended_statistics_update(positional_args)) result = false; PG_RETURN_BOOL(result); @@ -1758,17 +1755,17 @@ pg_clear_extended_stats(PG_FUNCTION_ARGS) Oid locked_table = InvalidOid; /* relation arguments */ - stats_check_required_arg(fcinfo, extarginfo, RELSCHEMA_ARG); + stats_check_required_arg(fcinfo->args, extarginfo, RELSCHEMA_ARG); relnspname = TextDatumGetCString(PG_GETARG_DATUM(RELSCHEMA_ARG)); - stats_check_required_arg(fcinfo, extarginfo, RELNAME_ARG); + stats_check_required_arg(fcinfo->args, extarginfo, RELNAME_ARG); relname = TextDatumGetCString(PG_GETARG_DATUM(RELNAME_ARG)); /* extended statistics arguments */ - stats_check_required_arg(fcinfo, extarginfo, STATSCHEMA_ARG); + stats_check_required_arg(fcinfo->args, extarginfo, STATSCHEMA_ARG); nspname = TextDatumGetCString(PG_GETARG_DATUM(STATSCHEMA_ARG)); - stats_check_required_arg(fcinfo, extarginfo, STATNAME_ARG); + stats_check_required_arg(fcinfo->args, extarginfo, STATNAME_ARG); stxname = TextDatumGetCString(PG_GETARG_DATUM(STATNAME_ARG)); - stats_check_required_arg(fcinfo, extarginfo, INHERITED_ARG); + stats_check_required_arg(fcinfo->args, extarginfo, INHERITED_ARG); inherited = PG_GETARG_BOOL(INHERITED_ARG); if (RecoveryInProgress()) diff --git a/src/backend/statistics/relation_stats.c b/src/backend/statistics/relation_stats.c index f2743c00c58..28d87fa6f77 100644 --- a/src/backend/statistics/relation_stats.c +++ b/src/backend/statistics/relation_stats.c @@ -59,26 +59,27 @@ 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, - FunctionCallInfo fcinfo); + const RelationStatsValues *statvalues); /* * 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; + RelationStatsValues values; - stats_check_required_arg(fcinfo, relarginfo, RELSCHEMA_ARG); - stats_check_required_arg(fcinfo, 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,14 +91,23 @@ relation_statistics_update(FunctionCallInfo fcinfo) ShareUpdateExclusiveLock, 0, RangeVarCallbackForStats, &locked_table); - return relation_statistics_update_internal(reloid, fcinfo); + /* 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, FunctionCallInfo fcinfo) +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, FunctionCallInfo fcinfo) int nreplaces = 0; bool result = true; - if (!PG_ARGISNULL(RELPAGES_ARG)) + if (!statvalues->relpages.isnull) { - relpages = PG_GETARG_INT32(RELPAGES_ARG); + relpages = DatumGetInt32(statvalues->relpages.value); update_relpages = true; } - if (!PG_ARGISNULL(RELTUPLES_ARG)) + if (!statvalues->reltuples.isnull) { - reltuples = PG_GETARG_FLOAT4(RELTUPLES_ARG); + reltuples = DatumGetFloat4(statvalues->reltuples.value); if (isnan(reltuples) || isinf(reltuples)) { ereport(WARNING, @@ -143,15 +153,15 @@ relation_statistics_update_internal(Oid reloid, FunctionCallInfo fcinfo) update_reltuples = true; } - if (!PG_ARGISNULL(RELALLVISIBLE_ARG)) + if (!statvalues->relallvisible.isnull) { - relallvisible = PG_GETARG_INT32(RELALLVISIBLE_ARG); + relallvisible = DatumGetInt32(statvalues->relallvisible.value); update_relallvisible = true; } - if (!PG_ARGISNULL(RELALLFROZEN_ARG)) + if (!statvalues->relallfrozen.isnull) { - relallfrozen = PG_GETARG_INT32(RELALLFROZEN_ARG); + relallfrozen = DatumGetInt32(statvalues->relallfrozen.value); update_relallfrozen = true; } @@ -223,84 +233,51 @@ relation_statistics_update_internal(Oid reloid, FunctionCallInfo fcinfo) Datum pg_clear_relation_stats(PG_FUNCTION_ARGS) { - LOCAL_FCINFO(newfcinfo, 6); + NullableDatum args[NUM_RELATION_STATS_ARGS]; - InitFunctionCallInfoData(*newfcinfo, NULL, 6, InvalidOid, NULL, NULL); + 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; - 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); + 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); } /* - * 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) { - LOCAL_FCINFO(newfcinfo, NUM_RELATION_STATS_ARGS); - - 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; - - newfcinfo->args[RELPAGES_ARG] = *relpages; - newfcinfo->args[RELTUPLES_ARG] = *reltuples; - newfcinfo->args[RELALLVISIBLE_ARG] = *relallvisible; - newfcinfo->args[RELALLFROZEN_ARG] = *relallfrozen; + Assert(statvalues); return relation_statistics_update_internal(RelationGetRelid(rel), - newfcinfo); + statvalues); } diff --git a/src/backend/statistics/stat_utils.c b/src/backend/statistics/stat_utils.c index f4ff9ab9b20..1cd00959b5c 100644 --- a/src/backend/statistics/stat_utils.c +++ b/src/backend/statistics/stat_utils.c @@ -51,11 +51,11 @@ static Node *statatt_get_index_expr(Relation rel, int attnum); * Ensure that a given argument is not null. */ void -stats_check_required_arg(FunctionCallInfo fcinfo, +stats_check_required_arg(const NullableDatum *args, struct StatsArgInfo *arginfo, int argnum) { - if (PG_ARGISNULL(argnum)) + if (args[argnum].isnull) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("argument \"%s\" must not be null", @@ -70,23 +70,21 @@ stats_check_required_arg(FunctionCallInfo fcinfo, * true. */ bool -stats_check_arg_array(FunctionCallInfo fcinfo, - struct StatsArgInfo *arginfo, - int argnum) +stats_check_arg_array(const NullableDatum *arg, const char *argname) { ArrayType *arr; - if (PG_ARGISNULL(argnum)) + if (arg->isnull) return true; - arr = DatumGetArrayTypeP(PG_GETARG_DATUM(argnum)); + 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(FunctionCallInfo fcinfo, 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(FunctionCallInfo fcinfo, * true. */ bool -stats_check_arg_pair(FunctionCallInfo fcinfo, - struct StatsArgInfo *arginfo, - int argnum1, int argnum2) +stats_check_arg_pair(const NullableDatum *arg1, const NullableDatum *arg2, + const char *argname1, const char *argname2) { - if (PG_ARGISNULL(argnum1) && PG_ARGISNULL(argnum2)) + if (arg1->isnull && arg2->isnull) return true; - if (PG_ARGISNULL(argnum1) || PG_ARGISNULL(argnum2)) + if (arg1->isnull || arg2->isnull) { - int nullarg = PG_ARGISNULL(argnum1) ? argnum1 : argnum2; - int otherarg = PG_ARGISNULL(argnum1) ? 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; } @@ -340,17 +336,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 +357,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, @@ -420,8 +416,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 15e962dbb7c..8544c064bbb 100644 --- a/src/include/statistics/stat_utils.h +++ b/src/include/statistics/stat_utils.h @@ -25,21 +25,22 @@ struct StatsArgInfo Oid argtype; }; -extern void stats_check_required_arg(FunctionCallInfo fcinfo, +extern void stats_check_required_arg(const NullableDatum *args, struct StatsArgInfo *arginfo, int argnum); -extern bool stats_check_arg_array(FunctionCallInfo fcinfo, - struct StatsArgInfo *arginfo, int argnum); -extern bool stats_check_arg_pair(FunctionCallInfo fcinfo, - 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); -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, diff --git a/src/include/statistics/statistics.h b/src/include/statistics/statistics.h index 0b163103a72..fa0430b9477 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/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list index c546b3d6375..fb3ee1b071b 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