From 3989477bca12fc513856002e1500dbc2e6b03497 Mon Sep 17 00:00:00 2001 From: justin Date: Wed, 9 Sep 2026 22:01:03 -0600 Subject: [PATCH 1/2] test: cover unread large constraint-backing index in pgTAP and _STATIC_CHECKS --- docs/health-checks/README.md | 1 + testing/pgTAP/04_medium_tests.sql | 11 ++++++++++- testing/seed_and_validate.py | 11 +++++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/docs/health-checks/README.md b/docs/health-checks/README.md index eda4049..5e2640c 100644 --- a/docs/health-checks/README.md +++ b/docs/health-checks/README.md @@ -48,6 +48,7 @@ A check only fires when its conditions are met, so an empty result for any check - **Tables Larger Than 50GB** - Identifies tables larger than 50GB (but less than 100GB) - **Query Duration Logging Disabled** - `log_min_duration_statement = -1` so slow queries never get logged - **Known Bug Affecting Your Version** - Notable non-CVE bugs from PostgreSQL release notes that match your running version (data integrity, replication, vacuum). Covers PG 15-18. +- **Unread Large Constraint-Backing Index** - Large unique or exclusion constraint indexes (>100MB, 0 scans) that are still enforced on every write but never used for reads. Review whether the underlying unique, primary-key, or exclusion constraint is still required before dropping the index. ## LOW Priority Issues diff --git a/testing/pgTAP/04_medium_tests.sql b/testing/pgTAP/04_medium_tests.sql index dbb7333..7d51fff 100644 --- a/testing/pgTAP/04_medium_tests.sql +++ b/testing/pgTAP/04_medium_tests.sql @@ -2,7 +2,7 @@ BEGIN; -- Cache results once; querying inline per-assertion multiplies execution cost by N. CREATE TEMP TABLE _pgfa_func_results AS SELECT * FROM pg_firstAid(); CREATE TEMP TABLE _pgfa_view_results AS SELECT * FROM v_pgfirstaid; -SELECT plan(18); +SELECT plan(20); SELECT ok( (SELECT count(*) >= 0 FROM _pgfa_func_results WHERE check_name = 'Missing FK Index'), @@ -85,5 +85,14 @@ SELECT ok( 'View executes Query Duration Logging Disabled check' ); +SELECT ok( + (SELECT count(*) >= 0 FROM _pgfa_func_results WHERE check_name = 'Unread Large Constraint-Backing Index'), + 'Function executes Unread Large Constraint-Backing Index check' +); +SELECT ok( + (SELECT count(*) >= 0 FROM _pgfa_view_results WHERE check_name = 'Unread Large Constraint-Backing Index'), + 'View executes Unread Large Constraint-Backing Index check' +); + SELECT * FROM finish(); ROLLBACK; diff --git a/testing/seed_and_validate.py b/testing/seed_and_validate.py index eba4223..6beddfa 100644 --- a/testing/seed_and_validate.py +++ b/testing/seed_and_validate.py @@ -692,6 +692,7 @@ def start_session_threads( "Role Never Logged In", "Empty Table", "Index With Very Low Usage", + "Unread Large Constraint-Backing Index", } ) @@ -738,6 +739,16 @@ def start_session_threads( "Replication Slots Near Max Wal Size", "Table Bloat (Detailed)", "Idle Connections Over 1 Hour", + "Autovacuum Disabled On Table", + "Timestamp Without Time Zone", + "Varchar With Length Limit", + "Serial Column Legacy", + "Rules On Tables", + "Query Duration Logging Disabled", + "listen_addresses Wildcard", + "Known CVE Affecting Your Version", + "Known Bug Affecting Your Version", + "Not In With Subquery", } ) From a9840b00f598e1a5bc20bfc52b762a01a2613f60 Mon Sep 17 00:00:00 2001 From: justin Date: Wed, 9 Sep 2026 22:06:45 -0600 Subject: [PATCH 2/2] fix(test): recategorize autovacuum and clarify constraint-backup guidance --- docs/health-checks/README.md | 2 +- testing/seed_and_validate.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/health-checks/README.md b/docs/health-checks/README.md index 5e2640c..1ec171a 100644 --- a/docs/health-checks/README.md +++ b/docs/health-checks/README.md @@ -48,7 +48,7 @@ A check only fires when its conditions are met, so an empty result for any check - **Tables Larger Than 50GB** - Identifies tables larger than 50GB (but less than 100GB) - **Query Duration Logging Disabled** - `log_min_duration_statement = -1` so slow queries never get logged - **Known Bug Affecting Your Version** - Notable non-CVE bugs from PostgreSQL release notes that match your running version (data integrity, replication, vacuum). Covers PG 15-18. -- **Unread Large Constraint-Backing Index** - Large unique or exclusion constraint indexes (>100MB, 0 scans) that are still enforced on every write but never used for reads. Review whether the underlying unique, primary-key, or exclusion constraint is still required before dropping the index. +- **Unread Large Constraint-Backing Index** - Large unique or exclusion indexes (>100MB, 0 scans) that are still enforced on every write but never used for reads. The check fires on any `indisunique` or `indisexclusion` index, regardless of whether it backs a constraint. To clear the row: drop the index directly if it is standalone, or drop the underlying unique, primary-key, or exclusion constraint (PostgreSQL does not allow `DROP INDEX` on a constraint-backed index). ## LOW Priority Issues diff --git a/testing/seed_and_validate.py b/testing/seed_and_validate.py index 6beddfa..700423a 100644 --- a/testing/seed_and_validate.py +++ b/testing/seed_and_validate.py @@ -693,6 +693,7 @@ def start_session_threads( "Empty Table", "Index With Very Low Usage", "Unread Large Constraint-Backing Index", + "Autovacuum Disabled On Table", } ) @@ -739,7 +740,6 @@ def start_session_threads( "Replication Slots Near Max Wal Size", "Table Bloat (Detailed)", "Idle Connections Over 1 Hour", - "Autovacuum Disabled On Table", "Timestamp Without Time Zone", "Varchar With Length Limit", "Serial Column Legacy",