postgres.git / summary / log / commit / refs
commit 302879bd68d1156fa27c38d29763ca9e4a1649c4
Author: Michael Paquier <michael@paquier.xyz>
Date: Mon Jan 26 23:20:13 2026 +0000
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 0e80f3f88dea for the restore function and
e1405aa5e3ac 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
doc/src/sgml/func/func-admin.sgml | 8 ++---
src/backend/statistics/extended_stats_funcs.c | 38 ++++++++++++++++++++++
src/test/regress/expected/stats_import.out | 45 +++++++++++++++++++++++++++
src/test/regress/sql/stats_import.sql | 29 +++++++++++++++++
4 files changed, 116 insertions(+), 4 deletions(-)
diff --git a/doc/src/sgml/func/func-admin.sgml b/doc/src/sgml/func/func-admin.sgml
index 3800cf3da09..ea42056bbc9 100644
--- a/doc/src/sgml/func/func-admin.sgml
+++ b/doc/src/sgml/func/func-admin.sgml
@@ -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
diff --git a/src/backend/statistics/extended_stats_funcs.c b/src/backend/statistics/extended_stats_funcs.c
index 48fa2efee76..18814093f50 100644
--- a/src/backend/statistics/extended_stats_funcs.c
+++ b/src/backend/statistics/extended_stats_funcs.c
@@ -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:
diff --git a/src/test/regress/expected/stats_import.out b/src/test/regress/expected/stats_import.out
index 9c2362e70c6..b5664e5513c 100644
--- a/src/test/regress/expected/stats_import.out
+++ b/src/test/regress/expected/stats_import.out
@@ -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
diff --git a/src/test/regress/sql/stats_import.sql b/src/test/regress/sql/stats_import.sql
index c9b1d9da2f7..3e70b817513 100644
--- a/src/test/regress/sql/stats_import.sql
+++ b/src/test/regress/sql/stats_import.sql
@@ -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
[parent: 19af794b660e]