]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Add support for "dependencies" in pg_restore_extended_stats()
authorMichael Paquier <michael@paquier.xyz>
Mon, 26 Jan 2026 23:20:13 +0000 (08:20 +0900)
committerMichael Paquier <michael@paquier.xyz>
Mon, 26 Jan 2026 23:20:13 +0000 (08:20 +0900)
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
src/backend/statistics/extended_stats_funcs.c
src/test/regress/expected/stats_import.out
src/test/regress/sql/stats_import.sql

index 3800cf3da09b65b147b858c9d2a9d4e87d6ee41c..ea42056bbc9bf7b2feeb9d0831d807b72479c0bc 100644 (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
index 48fa2efee76fc9e0b468df42e7f23b7ac6491562..18814093f509e162808d1aab760880986aaf1f5f 100644 (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:
index 9c2362e70c67942e4d437e96ae62f09d1fe0d52c..b5664e5513c14e86f104709fc1b989b63f070f65 100644 (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
index c9b1d9da2f7f224fe90e7efcbe5cbbf043f4535d..3e70b81751333ec8884078277a84d5bce0c9e781 100644 (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