Add support for "dependencies" in pg_restore_extended_stats()

This commit adds support for the restore of extended statistics of the
kind "dependencies", for the following input data:
[{"attributes": [2], "dependency": 3, "degree": 1.000000},
 {"attributes": [3], "dependency": 2, "degree": 1.000000}]

This relies on the existing routines of "dependencies" to cross-check
the input data with the definition of the extended statistics objects
for the attribute numbers.  An input argument of type "pg_dependencies"
is required for this new option.

Thanks to the work done in 0e80f3f88d for the restore function and
e1405aa5e3 for the input handling of data type pg_dependencies, this
addition is straight-forward.  This will be used so as it is possible to
transfer these statistics across dumps and upgrades, removing the need
for a post-operation ANALYZE for these kinds of statistics.

Author: Corey Huinker <corey.huinker@gmail.com>
Reviewed-by: Michael Paquier <michael@paquier.xyz>
Discussion: https://postgr.es/m/CADkLM=dpz3KFnqP-dgJ-zvRvtjsa8UZv8wDAQdqho=qN3kX0Zg@mail.gmail.com
This commit is contained in:
Michael Paquier 2026-01-27 08:20:13 +09:00
parent 19af794b66
commit 302879bd68
4 changed files with 116 additions and 4 deletions

View file

@ -2194,9 +2194,8 @@ SELECT pg_restore_attribute_stats(
</programlisting>
</para>
<para>
For example, to set the <structfield>n_distinct</structfield>,
<structfield>dependencies</structfield>, and <structfield>exprs</structfield>
values for the statistics object <structname>myschema.mystatsobj</structname>:
For example, to set some values for the statistics object
<structname>myschema.mystatsobj</structname>:
<programlisting>
SELECT pg_restore_extended_stats(
'schemaname', 'tab_schema'::name,
@ -2223,7 +2222,8 @@ SELECT pg_restore_attribute_stats(
Other arguments are the names and values of statistics corresponding
to columns in <link linkend="view-pg-stats-ext"><structname>pg_stats_ext</structname>
</link>.
This function currently supports <literal>n_distinct</literal>.
This function currently supports <literal>n_distinct</literal> and
<literal>dependencies</literal>.
</para>
<para>
Additionally, this function accepts argument name

View file

@ -45,6 +45,7 @@ enum extended_stats_argnum
STATNAME_ARG,
INHERITED_ARG,
NDISTINCT_ARG,
DEPENDENCIES_ARG,
NUM_EXTENDED_STATS_ARGS,
};
@ -60,6 +61,7 @@ static struct StatsArgInfo extarginfo[] =
[STATNAME_ARG] = {"statistics_name", TEXTOID},
[INHERITED_ARG] = {"inherited", BOOLOID},
[NDISTINCT_ARG] = {"n_distinct", PG_NDISTINCTOID},
[DEPENDENCIES_ARG] = {"dependencies", PG_DEPENDENCIESOID},
[NUM_EXTENDED_STATS_ARGS] = {0},
};
@ -257,6 +259,7 @@ extended_statistics_update(FunctionCallInfo fcinfo)
* were provided to the function.
*/
has.ndistinct = !PG_ARGISNULL(NDISTINCT_ARG);
has.dependencies = !PG_ARGISNULL(DEPENDENCIES_ARG);
if (RecoveryInProgress())
{
@ -355,6 +358,23 @@ extended_statistics_update(FunctionCallInfo fcinfo)
success = false;
}
/*
* If the object cannot support dependencies, we should not have data for
* it.
*/
if (has.dependencies && !enabled.dependencies)
{
ereport(WARNING,
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("cannot specify parameter \"%s\".",
extarginfo[DEPENDENCIES_ARG].argname),
errhint("Extended statistics object \"%s\".\"%s\" does not support statistics of this type.",
quote_identifier(nspname),
quote_identifier(stxname)));
has.dependencies = false;
success = false;
}
/*
* Populate the pg_statistic_ext_data result tuple.
*/
@ -396,6 +416,24 @@ extended_statistics_update(FunctionCallInfo fcinfo)
statext_ndistinct_free(ndistinct);
}
if (has.dependencies)
{
Datum dependencies_datum = PG_GETARG_DATUM(DEPENDENCIES_ARG);
bytea *data = DatumGetByteaPP(dependencies_datum);
MVDependencies *dependencies = statext_dependencies_deserialize(data);
if (statext_dependencies_validate(dependencies, &stxform->stxkeys, numexprs, WARNING))
{
values[Anum_pg_statistic_ext_data_stxddependencies - 1] = dependencies_datum;
nulls[Anum_pg_statistic_ext_data_stxddependencies - 1] = false;
replaces[Anum_pg_statistic_ext_data_stxddependencies - 1] = true;
}
else
success = false;
statext_dependencies_free(dependencies);
}
upsert_pg_statistic_ext_data(values, nulls, replaces);
cleanup:

View file

@ -1756,6 +1756,22 @@ HINT: Extended statistics object "stats_import"."test_stat_dependencies" does n
f
(1 row)
-- Incorrect extended stats kind, dependencies not supported
SELECT pg_catalog.pg_restore_extended_stats(
'schemaname', 'stats_import',
'relname', 'test',
'statistics_schemaname', 'stats_import',
'statistics_name', 'test_stat_ndistinct',
'inherited', false,
'dependencies', '[{"attributes": [2], "dependency": 3, "degree": 1.000000},
{"attributes": [3], "dependency": 2, "degree": 1.000000}]'::pg_dependencies);
WARNING: cannot specify parameter "dependencies".
HINT: Extended statistics object "stats_import"."test_stat_ndistinct" does not support statistics of this type.
pg_restore_extended_stats
---------------------------
f
(1 row)
-- ok: ndistinct
SELECT pg_catalog.pg_restore_extended_stats(
'schemaname', 'stats_import',
@ -1769,6 +1785,35 @@ SELECT pg_catalog.pg_restore_extended_stats(
t
(1 row)
-- dependencies value doesn't match definition
SELECT pg_catalog.pg_restore_extended_stats(
'schemaname', 'stats_import',
'relname', 'test',
'statistics_schemaname', 'stats_import',
'statistics_name', 'test_stat_dependencies',
'inherited', false,
'dependencies', '[{"attributes": [1], "dependency": 3, "degree": 1.000000},
{"attributes": [3], "dependency": 1, "degree": 1.000000}]'::pg_dependencies);
WARNING: could not validate "pg_dependencies" object: invalid attribute number 1 found
pg_restore_extended_stats
---------------------------
f
(1 row)
-- ok: dependencies
SELECT pg_catalog.pg_restore_extended_stats(
'schemaname', 'stats_import',
'relname', 'test',
'statistics_schemaname', 'stats_import',
'statistics_name', 'test_stat_dependencies',
'inherited', false,
'dependencies', '[{"attributes": [2], "dependency": 3, "degree": 1.000000},
{"attributes": [3], "dependency": 2, "degree": 1.000000}]'::pg_dependencies);
pg_restore_extended_stats
---------------------------
t
(1 row)
SELECT replace(e.n_distinct, '}, ', E'},\n') AS n_distinct
FROM pg_stats_ext AS e
WHERE e.statistics_schemaname = 'stats_import' AND

View file

@ -1258,6 +1258,15 @@ SELECT pg_catalog.pg_restore_extended_stats(
'statistics_name', 'test_stat_dependencies',
'inherited', false,
'n_distinct', '[{"attributes" : [1,3], "ndistinct" : 4}]'::pg_ndistinct);
-- Incorrect extended stats kind, dependencies not supported
SELECT pg_catalog.pg_restore_extended_stats(
'schemaname', 'stats_import',
'relname', 'test',
'statistics_schemaname', 'stats_import',
'statistics_name', 'test_stat_ndistinct',
'inherited', false,
'dependencies', '[{"attributes": [2], "dependency": 3, "degree": 1.000000},
{"attributes": [3], "dependency": 2, "degree": 1.000000}]'::pg_dependencies);
-- ok: ndistinct
SELECT pg_catalog.pg_restore_extended_stats(
@ -1268,6 +1277,26 @@ SELECT pg_catalog.pg_restore_extended_stats(
'inherited', false,
'n_distinct', '[{"attributes" : [2,3], "ndistinct" : 4}]'::pg_ndistinct);
-- dependencies value doesn't match definition
SELECT pg_catalog.pg_restore_extended_stats(
'schemaname', 'stats_import',
'relname', 'test',
'statistics_schemaname', 'stats_import',
'statistics_name', 'test_stat_dependencies',
'inherited', false,
'dependencies', '[{"attributes": [1], "dependency": 3, "degree": 1.000000},
{"attributes": [3], "dependency": 1, "degree": 1.000000}]'::pg_dependencies);
-- ok: dependencies
SELECT pg_catalog.pg_restore_extended_stats(
'schemaname', 'stats_import',
'relname', 'test',
'statistics_schemaname', 'stats_import',
'statistics_name', 'test_stat_dependencies',
'inherited', false,
'dependencies', '[{"attributes": [2], "dependency": 3, "degree": 1.000000},
{"attributes": [3], "dependency": 2, "degree": 1.000000}]'::pg_dependencies);
SELECT replace(e.n_distinct, '}, ', E'},\n') AS n_distinct
FROM pg_stats_ext AS e
WHERE e.statistics_schemaname = 'stats_import' AND