Hello!

While working on [1], I have found a small issue with correctness
of set_indexsafe_procflags usage in ReindexRelationConcurrently introduced
in [2].

> idx->safe = (indexRel->rd_indexprs == NIL && indexRel->rd_indpred == NIL);

It is always true because there are no RelationGetIndexExpressions
and RelationGetIndexPredicate before that check.

Two patches with reproducer + fix are attached.

The issue is simple, but I'll register this in commitfest just in case.

Best regards,
Mikhail.

[1]:
https://www.postgresql.org/message-id/flat/CANtu0ogBOtd9ravu1CUbuZWgq6qvn1rny38PGKDPk9zzQPH8_A%40mail.gmail.com#d4be02ff70f3002522f9fadbd165d631
[2]:
https://github.com/postgres/postgres/commit/f9900df5f94936067e6fa24a9df609863eb08da2
From 7dec20b6211cc2dca02d8806cf0a120236a24517 Mon Sep 17 00:00:00 2001
From: nkey <n...@toloka.ai>
Date: Fri, 6 Sep 2024 13:14:57 +0200
Subject: [PATCH v1 1/2] specification to reproduce issue with incorrect usage
 of set_indexsafe_procflags for REINDEX CONCURRENTLY

---
 src/backend/commands/indexcmds.c              |  3 +++
 src/test/modules/injection_points/Makefile    |  3 ++-
 .../reindex_concurrently_safe_index.out       |  9 ++++++++
 src/test/modules/injection_points/meson.build |  1 +
 .../reindex_concurrently_safe_index.spec      | 23 +++++++++++++++++++
 5 files changed, 38 insertions(+), 1 deletion(-)
 create mode 100644 src/test/modules/injection_points/expected/reindex_concurrently_safe_index.out
 create mode 100644 src/test/modules/injection_points/specs/reindex_concurrently_safe_index.spec

diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index c5a56c75f6..e07d279e2d 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -69,6 +69,7 @@
 #include "utils/regproc.h"
 #include "utils/snapmgr.h"
 #include "utils/syscache.h"
+#include "utils/injection_point.h"
 
 
 /* non-export function prototypes */
@@ -3784,6 +3785,8 @@ ReindexRelationConcurrently(const ReindexStmt *stmt, Oid relationOid, const Rein
 		/* determine safety of this index for set_indexsafe_procflags */
 		idx->safe = (indexRel->rd_indexprs == NIL &&
 					 indexRel->rd_indpred == NIL);
+		if (idx->safe)
+			INJECTION_POINT("ReindexRelationConcurrently_index_safe");
 		idx->tableId = RelationGetRelid(heapRel);
 		idx->amId = indexRel->rd_rel->relam;
 
diff --git a/src/test/modules/injection_points/Makefile b/src/test/modules/injection_points/Makefile
index 1c1c2d0b13..7d85e25d4b 100644
--- a/src/test/modules/injection_points/Makefile
+++ b/src/test/modules/injection_points/Makefile
@@ -13,7 +13,8 @@ PGFILEDESC = "injection_points - facility for injection points"
 REGRESS = injection_points
 REGRESS_OPTS = --dlpath=$(top_builddir)/src/test/regress
 
-ISOLATION = inplace
+ISOLATION = inplace \
+			reindex_concurrently_safe_index
 
 TAP_TESTS = 1
 
diff --git a/src/test/modules/injection_points/expected/reindex_concurrently_safe_index.out b/src/test/modules/injection_points/expected/reindex_concurrently_safe_index.out
new file mode 100644
index 0000000000..c36033ffe4
--- /dev/null
+++ b/src/test/modules/injection_points/expected/reindex_concurrently_safe_index.out
@@ -0,0 +1,9 @@
+Parsed test spec with 1 sessions
+
+starting permutation: reindex
+injection_points_attach
+-----------------------
+                       
+(1 row)
+
+step reindex: REINDEX INDEX CONCURRENTLY test.tbl_pkey_not_safe;
diff --git a/src/test/modules/injection_points/meson.build b/src/test/modules/injection_points/meson.build
index c9e357f644..aeb47cbd8f 100644
--- a/src/test/modules/injection_points/meson.build
+++ b/src/test/modules/injection_points/meson.build
@@ -42,6 +42,7 @@ tests += {
   'isolation': {
     'specs': [
       'inplace',
+      'reindex_concurrently_safe_index',
     ],
   },
   'tap': {
diff --git a/src/test/modules/injection_points/specs/reindex_concurrently_safe_index.spec b/src/test/modules/injection_points/specs/reindex_concurrently_safe_index.spec
new file mode 100644
index 0000000000..dc2ebe02bf
--- /dev/null
+++ b/src/test/modules/injection_points/specs/reindex_concurrently_safe_index.spec
@@ -0,0 +1,23 @@
+setup
+{
+	CREATE EXTENSION injection_points;
+	CREATE SCHEMA test;
+	CREATE TABLE test.tbl(i int primary key, updated_at timestamp);
+	CREATE UNIQUE INDEX tbl_pkey_not_safe ON test.tbl(ABS(i)) WHERE MOD(i, 2) = 0;
+}
+
+teardown
+{
+	DROP SCHEMA test CASCADE;
+	DROP EXTENSION injection_points;
+}
+
+session test
+setup	{
+	SELECT injection_points_set_local();
+	SELECT injection_points_attach('ReindexRelationConcurrently_index_safe', 'error');
+}
+step reindex	{ REINDEX INDEX CONCURRENTLY test.tbl_pkey_not_safe; }
+
+permutation
+	reindex
\ No newline at end of file
-- 
2.43.0

From 3479ee2848c3022aa31d8b5a1ff3389b82eb13fe Mon Sep 17 00:00:00 2001
From: nkey <n...@toloka.ai>
Date: Fri, 6 Sep 2024 13:17:51 +0200
Subject: [PATCH v1 2/2] Ensure the correct determination of index safety to be
 used with set_indexsafe_procflags during REINDEX CONCURRENTLY

---
 src/backend/commands/indexcmds.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index e07d279e2d..c34c550b4a 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -3783,8 +3783,8 @@ ReindexRelationConcurrently(const ReindexStmt *stmt, Oid relationOid, const Rein
 		RestrictSearchPath();
 
 		/* determine safety of this index for set_indexsafe_procflags */
-		idx->safe = (indexRel->rd_indexprs == NIL &&
-					 indexRel->rd_indpred == NIL);
+		idx->safe = (RelationGetIndexExpressions(indexRel) == NIL &&
+				RelationGetIndexPredicate(indexRel) == NIL);
 		if (idx->safe)
 			INJECTION_POINT("ReindexRelationConcurrently_index_safe");
 		idx->tableId = RelationGetRelid(heapRel);
-- 
2.43.0

Reply via email to