From 66f85615d5d650c47b6e8ea75e32a6817cb23dac Mon Sep 17 00:00:00 2001 From: Michael Paquier Date: Wed, 2 Sep 2026 16:22:32 +0900 Subject: [PATCH] Add more test coverage for pg_clear_attribute_stats() pg_clear_attribute_stats() was called exactly once in the whole test suite, only for a correct cleanup. None of its failure scenarios were covered, in terms of: - NULL input values - Incorrect object names (schema, attribute, relation) - Incorrect relkinds - Inherited pg_statistic entry cleanup All these cases are now covered. This would have caught the failure fixed by 11ed011ae22, as one example. Author: Zhong ShiHao Discussion: https://postgr.es/m/CAGRkXqQEFzVh_bQSoLGDqaRTq7Xta6OUoda8PDrWDPWcAuwk=w@mail.gmail.com --- src/test/regress/expected/stats_import.out | 137 +++++++++++++++++++++ src/test/regress/sql/stats_import.sql | 96 +++++++++++++++ 2 files changed, 233 insertions(+) diff --git a/src/test/regress/expected/stats_import.out b/src/test/regress/expected/stats_import.out index f3f915e7ed1..4ce176c2667 100644 --- a/src/test/regress/expected/stats_import.out +++ b/src/test/regress/expected/stats_import.out @@ -1637,6 +1637,143 @@ AND attname = 'arange'; 0 (1 row) +-- Tests for pg_clear_attribute_stats() +-- Invalid argument values. +SELECT pg_catalog.pg_clear_attribute_stats( + schemaname => NULL, + relname => 'test', + attname => 'arange', + inherited => false); +ERROR: argument "schemaname" must not be null +SELECT pg_catalog.pg_clear_attribute_stats( + schemaname => 'stats_import', + relname => NULL, + attname => 'arange', + inherited => false); +ERROR: argument "relname" must not be null +SELECT pg_catalog.pg_clear_attribute_stats( + schemaname => 'stats_import', + relname => 'test', + attname => NULL, + inherited => false); +ERROR: argument "attname" must not be null +SELECT pg_catalog.pg_clear_attribute_stats( + schemaname => 'stats_import', + relname => 'test', + attname => 'arange', + inherited => NULL); +ERROR: argument "inherited" must not be null +-- Missing objects +SELECT pg_catalog.pg_clear_attribute_stats( + schemaname => 'schema_not_exist', + relname => 'test', + attname => 'arange', + inherited => false); +ERROR: schema "schema_not_exist" does not exist +SELECT pg_catalog.pg_clear_attribute_stats( + schemaname => 'stats_import', + relname => 'table_not_exist', + attname => 'arange', + inherited => false); +ERROR: relation "stats_import.table_not_exist" does not exist +SELECT pg_catalog.pg_clear_attribute_stats( + schemaname => 'stats_import', + relname => 'test', + attname => 'att_not_exist', + inherited => false); +ERROR: column "att_not_exist" of relation "test" does not exist +-- error: system column +SELECT pg_catalog.pg_clear_attribute_stats( + schemaname => 'stats_import', + relname => 'test', + attname => 'ctid', + inherited => false); +ERROR: cannot clear statistics on system column "ctid" +-- error: relkinds +SELECT pg_catalog.pg_clear_attribute_stats( + schemaname => 'stats_import', + relname => 'testseq', + attname => 'last_value', + inherited => false); +ERROR: cannot modify statistics for relation "testseq" +DETAIL: This operation is not supported for sequences. +SELECT pg_catalog.pg_clear_attribute_stats( + schemaname => 'stats_import', + relname => 'testview', + attname => 'id', + inherited => false); +ERROR: cannot modify statistics for relation "testview" +DETAIL: This operation is not supported for views. +-- Inherited stats are held in separate pg_statistic rows, and only the +-- rows matching the inherited argument are removed. Plant one of each +-- for the same column, clear the inherited one, and check that the +-- non-inherited one survives. +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attname', 'arange', + 'inherited', false::boolean, + 'null_frac', 0.5::real); + pg_restore_attribute_stats +---------------------------- + t +(1 row) + +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attname', 'arange', + 'inherited', true::boolean, + 'null_frac', 0.5::real); + pg_restore_attribute_stats +---------------------------- + t +(1 row) + +SELECT inherited, count(*) + FROM pg_stats + WHERE schemaname = 'stats_import' + AND tablename = 'test' + AND attname = 'arange' + GROUP BY inherited ORDER BY inherited; + inherited | count +-----------+------- + f | 1 + t | 1 +(2 rows) + +SELECT pg_catalog.pg_clear_attribute_stats( + schemaname => 'stats_import', + relname => 'test', + attname => 'arange', + inherited => true); + pg_clear_attribute_stats +-------------------------- + +(1 row) + +SELECT inherited, count(*) + FROM pg_stats + WHERE schemaname = 'stats_import' + AND tablename = 'test' + AND attname = 'arange' + GROUP BY inherited ORDER BY inherited; + inherited | count +-----------+------- + f | 1 +(1 row) + +-- Clean up the non-inherited row planted above. +SELECT pg_catalog.pg_clear_attribute_stats( + schemaname => 'stats_import', + relname => 'test', + attname => 'arange', + inherited => false); + pg_clear_attribute_stats +-------------------------- + +(1 row) + -- temp tables CREATE TEMP TABLE stats_temp(i int); SELECT pg_restore_relation_stats( diff --git a/src/test/regress/sql/stats_import.sql b/src/test/regress/sql/stats_import.sql index 334d7d8dc00..748c9a2e000 100644 --- a/src/test/regress/sql/stats_import.sql +++ b/src/test/regress/sql/stats_import.sql @@ -1207,6 +1207,102 @@ AND tablename = 'test' AND inherited = false AND attname = 'arange'; +-- Tests for pg_clear_attribute_stats() +-- Invalid argument values. +SELECT pg_catalog.pg_clear_attribute_stats( + schemaname => NULL, + relname => 'test', + attname => 'arange', + inherited => false); +SELECT pg_catalog.pg_clear_attribute_stats( + schemaname => 'stats_import', + relname => NULL, + attname => 'arange', + inherited => false); +SELECT pg_catalog.pg_clear_attribute_stats( + schemaname => 'stats_import', + relname => 'test', + attname => NULL, + inherited => false); +SELECT pg_catalog.pg_clear_attribute_stats( + schemaname => 'stats_import', + relname => 'test', + attname => 'arange', + inherited => NULL); +-- Missing objects +SELECT pg_catalog.pg_clear_attribute_stats( + schemaname => 'schema_not_exist', + relname => 'test', + attname => 'arange', + inherited => false); +SELECT pg_catalog.pg_clear_attribute_stats( + schemaname => 'stats_import', + relname => 'table_not_exist', + attname => 'arange', + inherited => false); +SELECT pg_catalog.pg_clear_attribute_stats( + schemaname => 'stats_import', + relname => 'test', + attname => 'att_not_exist', + inherited => false); +-- error: system column +SELECT pg_catalog.pg_clear_attribute_stats( + schemaname => 'stats_import', + relname => 'test', + attname => 'ctid', + inherited => false); +-- error: relkinds +SELECT pg_catalog.pg_clear_attribute_stats( + schemaname => 'stats_import', + relname => 'testseq', + attname => 'last_value', + inherited => false); +SELECT pg_catalog.pg_clear_attribute_stats( + schemaname => 'stats_import', + relname => 'testview', + attname => 'id', + inherited => false); + +-- Inherited stats are held in separate pg_statistic rows, and only the +-- rows matching the inherited argument are removed. Plant one of each +-- for the same column, clear the inherited one, and check that the +-- non-inherited one survives. +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attname', 'arange', + 'inherited', false::boolean, + 'null_frac', 0.5::real); +SELECT pg_catalog.pg_restore_attribute_stats( + 'schemaname', 'stats_import', + 'relname', 'test', + 'attname', 'arange', + 'inherited', true::boolean, + 'null_frac', 0.5::real); +SELECT inherited, count(*) + FROM pg_stats + WHERE schemaname = 'stats_import' + AND tablename = 'test' + AND attname = 'arange' + GROUP BY inherited ORDER BY inherited; +SELECT pg_catalog.pg_clear_attribute_stats( + schemaname => 'stats_import', + relname => 'test', + attname => 'arange', + inherited => true); +SELECT inherited, count(*) + FROM pg_stats + WHERE schemaname = 'stats_import' + AND tablename = 'test' + AND attname = 'arange' + GROUP BY inherited ORDER BY inherited; +-- Clean up the non-inherited row planted above. +SELECT pg_catalog.pg_clear_attribute_stats( + schemaname => 'stats_import', + relname => 'test', + attname => 'arange', + inherited => false); + -- temp tables CREATE TEMP TABLE stats_temp(i int); SELECT pg_restore_relation_stats(