From ef1fdbef72f8ac090f01b6d8432d6fb4f8971bee Mon Sep 17 00:00:00 2001
From: ChangAo Chen <cca5507@qq.com>
Date: Tue, 23 Jun 2026 13:04:11 +0800
Subject: [PATCH v3 2/2] Add test case for vacuum with a concurrent drop.

---
 src/backend/commands/vacuum.c                 |  2 +
 src/test/modules/injection_points/Makefile    |  1 +
 .../expected/vacuum_concurrent_drop.out       | 65 +++++++++++++++++++
 src/test/modules/injection_points/meson.build |  1 +
 .../specs/vacuum_concurrent_drop.spec         | 64 ++++++++++++++++++
 5 files changed, 133 insertions(+)
 create mode 100644 src/test/modules/injection_points/expected/vacuum_concurrent_drop.out
 create mode 100644 src/test/modules/injection_points/specs/vacuum_concurrent_drop.spec

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 2217188d86e..d895b31be6b 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -1069,6 +1069,8 @@ get_all_vacuum_rels(MemoryContext vac_context, int options)
 
 	scan = table_beginscan_catalog(pgclass, 0, NULL);
 
+	INJECTION_POINT("vacuum-constructing-vacuumable-rels", NULL);
+
 	while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
 	{
 		Form_pg_class classForm = (Form_pg_class) GETSTRUCT(tuple);
diff --git a/src/test/modules/injection_points/Makefile b/src/test/modules/injection_points/Makefile
index c01d2fb095c..2fae0e01f15 100644
--- a/src/test/modules/injection_points/Makefile
+++ b/src/test/modules/injection_points/Makefile
@@ -18,6 +18,7 @@ ISOLATION = basic \
 	    repack_temporal \
 	    repack_temporal_multirange \
 	    repack_toast \
+		vacuum_concurrent_drop \
 	    syscache-update-pruned \
 	    heap_lock_update
 
diff --git a/src/test/modules/injection_points/expected/vacuum_concurrent_drop.out b/src/test/modules/injection_points/expected/vacuum_concurrent_drop.out
new file mode 100644
index 00000000000..c46b267a27f
--- /dev/null
+++ b/src/test/modules/injection_points/expected/vacuum_concurrent_drop.out
@@ -0,0 +1,65 @@
+Parsed test spec with 2 sessions
+
+starting permutation: create1 setrole1 vacuum1 drop2 wakeup2 resetrole1
+step create1: 
+    CREATE TABLE foo (id int);
+
+step setrole1: 
+    SET ROLE regress_vacuum;
+
+step vacuum1: 
+    VACUUM;
+ <waiting ...>
+step drop2: 
+    DROP TABLE foo;
+
+step wakeup2: 
+    SELECT injection_points_wakeup('vacuum-constructing-vacuumable-rels');
+
+injection_points_wakeup
+-----------------------
+                       
+(1 row)
+
+s1: WARNING:  skipping vacuum of "foo" --- relation no longer exists
+step vacuum1: <... completed>
+step resetrole1: 
+    RESET ROLE;
+
+injection_points_detach
+-----------------------
+                       
+(1 row)
+
+
+starting permutation: create1 setrole1 analyze1 drop2 wakeup2 resetrole1
+step create1: 
+    CREATE TABLE foo (id int);
+
+step setrole1: 
+    SET ROLE regress_vacuum;
+
+step analyze1: 
+    ANALYZE;
+ <waiting ...>
+step drop2: 
+    DROP TABLE foo;
+
+step wakeup2: 
+    SELECT injection_points_wakeup('vacuum-constructing-vacuumable-rels');
+
+injection_points_wakeup
+-----------------------
+                       
+(1 row)
+
+s1: WARNING:  skipping analyze of "foo" --- relation no longer exists
+step analyze1: <... completed>
+step resetrole1: 
+    RESET ROLE;
+
+injection_points_detach
+-----------------------
+                       
+(1 row)
+
diff --git a/src/test/modules/injection_points/meson.build b/src/test/modules/injection_points/meson.build
index 59dba1cb023..dbb1edf0bfe 100644
--- a/src/test/modules/injection_points/meson.build
+++ b/src/test/modules/injection_points/meson.build
@@ -49,6 +49,7 @@ tests += {
       'repack_temporal',
       'repack_temporal_multirange',
       'repack_toast',
+      'vacuum_concurrent_drop',
       'syscache-update-pruned',
       'heap_lock_update',
     ],
diff --git a/src/test/modules/injection_points/specs/vacuum_concurrent_drop.spec b/src/test/modules/injection_points/specs/vacuum_concurrent_drop.spec
new file mode 100644
index 00000000000..793a12762ae
--- /dev/null
+++ b/src/test/modules/injection_points/specs/vacuum_concurrent_drop.spec
@@ -0,0 +1,64 @@
+# Test vacuum/analyze with a concurrent drop when constructing the list
+# of vacuumable relations. The vacuum/analyze should not error out when
+# a concurrent drop happens.
+
+setup
+{
+	CREATE EXTENSION injection_points;
+    CREATE ROLE regress_vacuum IN ROLE pg_maintain;
+}
+teardown
+{
+    DROP ROLE regress_vacuum;
+	DROP EXTENSION injection_points;
+}
+
+session s1
+setup
+{
+	SELECT injection_points_set_local();
+	SELECT injection_points_attach('vacuum-constructing-vacuumable-rels', 'wait');
+    SET client_min_messages = WARNING;
+}
+step create1
+{
+    CREATE TABLE foo (id int);
+}
+# Make sure that current user is not the owner of current database.
+step setrole1
+{
+    SET ROLE regress_vacuum;
+}
+step vacuum1
+{
+    VACUUM;
+}
+step analyze1
+{
+    ANALYZE;
+}
+step resetrole1
+{
+    RESET ROLE;
+}
+teardown
+{
+    RESET client_min_messages;
+	SELECT injection_points_detach('vacuum-constructing-vacuumable-rels');
+}
+
+session s2
+step drop2
+{
+    DROP TABLE foo;
+}
+step wakeup2
+{
+    SELECT injection_points_wakeup('vacuum-constructing-vacuumable-rels');
+}
+
+# Test vacuum
+permutation create1 setrole1 vacuum1 drop2 wakeup2 resetrole1
+
+# Test analyze
+permutation create1 setrole1 analyze1 drop2 wakeup2 resetrole1
-- 
2.34.1

