v1-0002-pgstat_drop_relation-for-indexes.patch

text/plain

Filename: v1-0002-pgstat_drop_relation-for-indexes.patch
Type: text/plain
Part: 0
Message: Re: pg_stat_have_stats() returns true for dropped indexes (or for index creation transaction rolled back)

Patch

Format: unified
Series: patch v1-0002
File+
src/backend/catalog/heap.c 3 3
src/backend/catalog/index.c 3 0
src/test/regress/expected/stats.out 154 0
src/test/regress/sql/stats.sql 68 0
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index 9b03579e6e..9a80ccdccd 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -403,6 +403,9 @@ heap_create(const char *relname,
 		recordDependencyOnTablespace(RelationRelationId, relid,
 									 reltablespace);
 
+	/* ensure that stats are dropped if transaction aborts */
+	pgstat_create_relation(rel);
+
 	return rel;
 }
 
@@ -1477,9 +1480,6 @@ heap_create_with_catalog(const char *relname,
 	if (oncommit != ONCOMMIT_NOOP)
 		register_on_commit_action(relid, oncommit);
 
-	/* ensure that stats are dropped if transaction aborts */
-	pgstat_create_relation(new_rel_desc);
-
 	/*
 	 * ok, the relation has been cataloged, so close our relations and return
 	 * the OID of the newly created relation.
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index d7192f35e3..61f1d3926a 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -2325,6 +2325,9 @@ index_drop(Oid indexId, bool concurrent, bool concurrent_lock_mode)
 	if (RELKIND_HAS_STORAGE(userIndexRelation->rd_rel->relkind))
 		RelationDropStorage(userIndexRelation);
 
+	/* ensure that stats are dropped if transaction commits */
+	pgstat_drop_relation(userIndexRelation);
+
 	/*
 	 * Close and flush the index's relcache entry, to ensure relcache doesn't
 	 * try to rebuild it while we're deleting catalog entries. We keep the
diff --git a/src/test/regress/expected/stats.out b/src/test/regress/expected/stats.out
index 6b233ff4c0..5b01ef68fe 100644
--- a/src/test/regress/expected/stats.out
+++ b/src/test/regress/expected/stats.out
@@ -783,6 +783,160 @@ SELECT pg_stat_have_stats('database', (SELECT oid FROM pg_database WHERE datname
  t
 (1 row)
 
+-- pg_stat_have_stats returns true for table creation inserting data
+CREATE table stats_test_tab1 as select generate_series(1,10) a;
+SELECT 'stats_test_tab1'::regclass::oid AS stats_test_tab1_oid \gset
+SELECT oid AS dboid from pg_database where datname = current_database() \gset
+SELECT pg_stat_have_stats('relation', :dboid, :stats_test_tab1_oid);
+ pg_stat_have_stats 
+--------------------
+ t
+(1 row)
+
+-- pg_stat_have_stats returns true for a rolled back drop table with stats
+BEGIN;
+SELECT pg_stat_have_stats('relation', :dboid, :stats_test_tab1_oid);
+ pg_stat_have_stats 
+--------------------
+ t
+(1 row)
+
+DROP table stats_test_tab1;
+ROLLBACK;
+SELECT pg_stat_have_stats('relation', :dboid, :stats_test_tab1_oid);
+ pg_stat_have_stats 
+--------------------
+ t
+(1 row)
+
+-- pg_stat_have_stats returns false for a dropped table with stats
+SELECT pg_stat_have_stats('relation', :dboid, :stats_test_tab1_oid);
+ pg_stat_have_stats 
+--------------------
+ t
+(1 row)
+
+DROP table stats_test_tab1;
+SELECT pg_stat_have_stats('relation', :dboid, :stats_test_tab1_oid);
+ pg_stat_have_stats 
+--------------------
+ f
+(1 row)
+
+-- pg_stat_have_stats returns false for rolled back table creation inserting data
+BEGIN;
+CREATE table stats_test_tab1 as select generate_series(1,10) a;
+SELECT 'stats_test_tab1'::regclass::oid AS stats_test_tab1_oid \gset
+ROLLBACK;
+SELECT pg_stat_have_stats('relation', :dboid, :stats_test_tab1_oid);
+ pg_stat_have_stats 
+--------------------
+ f
+(1 row)
+
+-- pg_stat_have_stats returns true for committed index creation
+CREATE table stats_test_tab1 as select generate_series(1,10) a;
+CREATE index stats_test_idx1 on stats_test_tab1(a);
+SELECT 'stats_test_idx1'::regclass::oid AS stats_test_idx1_oid \gset
+SET enable_seqscan TO off;
+select a from stats_test_tab1 where a = 3;
+ a 
+---
+ 3
+(1 row)
+
+SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+ pg_stat_have_stats 
+--------------------
+ t
+(1 row)
+
+-- pg_stat_have_stats returns false for dropped index with stats
+SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+ pg_stat_have_stats 
+--------------------
+ t
+(1 row)
+
+DROP index stats_test_idx1;
+SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+ pg_stat_have_stats 
+--------------------
+ f
+(1 row)
+
+-- pg_stat_have_stats returns false for rolled back index creation
+BEGIN;
+CREATE index stats_test_idx1 on stats_test_tab1(a);
+SELECT 'stats_test_idx1'::regclass::oid AS stats_test_idx1_oid \gset
+select a from stats_test_tab1 where a = 3;
+ a 
+---
+ 3
+(1 row)
+
+SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+ pg_stat_have_stats 
+--------------------
+ t
+(1 row)
+
+ROLLBACK;
+SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+ pg_stat_have_stats 
+--------------------
+ f
+(1 row)
+
+-- pg_stat_have_stats returns true for reindex CONCURRENTLY
+CREATE index stats_test_idx1 on stats_test_tab1(a);
+SELECT 'stats_test_idx1'::regclass::oid AS stats_test_idx1_oid \gset
+select a from stats_test_tab1 where a = 3;
+ a 
+---
+ 3
+(1 row)
+
+SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+ pg_stat_have_stats 
+--------------------
+ t
+(1 row)
+
+REINDEX index CONCURRENTLY stats_test_idx1;
+-- false for previous oid
+SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+ pg_stat_have_stats 
+--------------------
+ f
+(1 row)
+
+-- true for new oid
+SELECT 'stats_test_idx1'::regclass::oid AS stats_test_idx1_oid \gset
+SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+ pg_stat_have_stats 
+--------------------
+ t
+(1 row)
+
+-- pg_stat_have_stats returns true for a rolled back drop index with stats
+BEGIN;
+SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+ pg_stat_have_stats 
+--------------------
+ t
+(1 row)
+
+DROP index stats_test_idx1;
+ROLLBACK;
+SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+ pg_stat_have_stats 
+--------------------
+ t
+(1 row)
+
+-- put enable_seqscan back to on
+SET enable_seqscan TO on;
 -- ensure that stats accessors handle NULL input correctly
 SELECT pg_stat_get_replication_slot(NULL);
  pg_stat_get_replication_slot 
diff --git a/src/test/regress/sql/stats.sql b/src/test/regress/sql/stats.sql
index 096f00ce8b..7cfefb2abc 100644
--- a/src/test/regress/sql/stats.sql
+++ b/src/test/regress/sql/stats.sql
@@ -390,6 +390,74 @@ SELECT pg_stat_have_stats('zaphod', 0, 0);
 SELECT pg_stat_have_stats('database', (SELECT oid FROM pg_database WHERE datname = current_database()), 1);
 SELECT pg_stat_have_stats('database', (SELECT oid FROM pg_database WHERE datname = current_database()), 0);
 
+-- pg_stat_have_stats returns true for table creation inserting data
+CREATE table stats_test_tab1 as select generate_series(1,10) a;
+SELECT 'stats_test_tab1'::regclass::oid AS stats_test_tab1_oid \gset
+SELECT oid AS dboid from pg_database where datname = current_database() \gset
+SELECT pg_stat_have_stats('relation', :dboid, :stats_test_tab1_oid);
+
+-- pg_stat_have_stats returns true for a rolled back drop table with stats
+BEGIN;
+SELECT pg_stat_have_stats('relation', :dboid, :stats_test_tab1_oid);
+DROP table stats_test_tab1;
+ROLLBACK;
+SELECT pg_stat_have_stats('relation', :dboid, :stats_test_tab1_oid);
+
+-- pg_stat_have_stats returns false for a dropped table with stats
+SELECT pg_stat_have_stats('relation', :dboid, :stats_test_tab1_oid);
+DROP table stats_test_tab1;
+SELECT pg_stat_have_stats('relation', :dboid, :stats_test_tab1_oid);
+
+-- pg_stat_have_stats returns false for rolled back table creation inserting data
+BEGIN;
+CREATE table stats_test_tab1 as select generate_series(1,10) a;
+SELECT 'stats_test_tab1'::regclass::oid AS stats_test_tab1_oid \gset
+ROLLBACK;
+SELECT pg_stat_have_stats('relation', :dboid, :stats_test_tab1_oid);
+
+-- pg_stat_have_stats returns true for committed index creation
+CREATE table stats_test_tab1 as select generate_series(1,10) a;
+CREATE index stats_test_idx1 on stats_test_tab1(a);
+SELECT 'stats_test_idx1'::regclass::oid AS stats_test_idx1_oid \gset
+SET enable_seqscan TO off;
+select a from stats_test_tab1 where a = 3;
+SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+
+-- pg_stat_have_stats returns false for dropped index with stats
+SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+DROP index stats_test_idx1;
+SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+
+-- pg_stat_have_stats returns false for rolled back index creation
+BEGIN;
+CREATE index stats_test_idx1 on stats_test_tab1(a);
+SELECT 'stats_test_idx1'::regclass::oid AS stats_test_idx1_oid \gset
+select a from stats_test_tab1 where a = 3;
+SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+ROLLBACK;
+SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+
+-- pg_stat_have_stats returns true for reindex CONCURRENTLY
+CREATE index stats_test_idx1 on stats_test_tab1(a);
+SELECT 'stats_test_idx1'::regclass::oid AS stats_test_idx1_oid \gset
+select a from stats_test_tab1 where a = 3;
+SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+REINDEX index CONCURRENTLY stats_test_idx1;
+-- false for previous oid
+SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+-- true for new oid
+SELECT 'stats_test_idx1'::regclass::oid AS stats_test_idx1_oid \gset
+SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+
+-- pg_stat_have_stats returns true for a rolled back drop index with stats
+BEGIN;
+SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+DROP index stats_test_idx1;
+ROLLBACK;
+SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+
+-- put enable_seqscan back to on
+SET enable_seqscan TO on;
 
 -- ensure that stats accessors handle NULL input correctly
 SELECT pg_stat_get_replication_slot(NULL);