0001-Use-more-safe-procedure-to-check-a-non-transactional.patch
text/plain
Filename: 0001-Use-more-safe-procedure-to-check-a-non-transactional.patch
Type: text/plain
Part: 0
Patch
Format: format-patch
Series: patch 0001
Subject: Use more safe procedure to check a non-transactional CONCURRENT operation on transactional updates.
| File | + | − |
|---|---|---|
| src/backend/catalog/index.c | 6 | 2 |
| src/test/regress/expected/create_index.out | 17 | 0 |
| src/test/regress/sql/create_index.sql | 13 | 0 |
From 2d658eb9830c78e875b08daa86c608d5f327b1f3 Mon Sep 17 00:00:00 2001
From: "Andrey V. Lepikhov" <a.lepikhov@postgrespro.ru>
Date: Sat, 26 Jun 2021 19:54:25 +0300
Subject: [PATCH] Use more safe procedure to check a non-transactional
CONCURRENT operation on transactional updates.
---
src/backend/catalog/index.c | 8 ++++++--
src/test/regress/expected/create_index.out | 17 +++++++++++++++++
src/test/regress/sql/create_index.sql | 13 +++++++++++++
3 files changed, 36 insertions(+), 2 deletions(-)
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index b9eed8ec38..ca91a7c74f 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -3395,8 +3395,12 @@ index_set_state_flags(Oid indexId, IndexStateFlagsAction action)
HeapTuple indexTuple;
Form_pg_index indexForm;
- /* Assert that current xact hasn't done any transactional updates */
- Assert(GetTopTransactionIdIfAny() == InvalidTransactionId);
+ /* Check that current xact hasn't done any transactional updates */
+ if (GetTopTransactionIdIfAny() != InvalidTransactionId)
+ ereport(ERROR,
+ (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
+ errmsg("Some transactional updates were made during a concurrent index operation")));
+
/* Open pg_index and fetch a writable copy of the index's tuple */
pg_index = table_open(IndexRelationId, RowExclusiveLock);
diff --git a/src/test/regress/expected/create_index.out b/src/test/regress/expected/create_index.out
index 8e11c089b1..93103334d8 100644
--- a/src/test/regress/expected/create_index.out
+++ b/src/test/regress/expected/create_index.out
@@ -1393,6 +1393,23 @@ BEGIN;
CREATE INDEX CONCURRENTLY concur_index7 ON concur_heap(f1);
ERROR: CREATE INDEX CONCURRENTLY cannot run inside a transaction block
COMMIT;
+CREATE FUNCTION predicate() RETURNS bool IMMUTABLE LANGUAGE plpgsql AS $$
+BEGIN
+ EXECUTE 'SELECT txid_current()';
+ RETURN true;
+END; $$;
+-- You can't do any transactional updates during concurrent index build.
+CREATE INDEX CONCURRENTLY concur_index8 ON concur_heap (f1) WHERE predicate();
+ERROR: Some transactional updates were made during a concurrent index operation
+-- Index exists but invalid. It must be actualized after REINDEX TABLE command.
+SELECT relname,indisvalid FROM pg_class, pg_index
+ WHERE relname = 'concur_index8' AND oid = indexrelid;
+ relname | indisvalid
+---------------+------------
+ concur_index8 | f
+(1 row)
+
+DROP INDEX concur_index8;
-- But you can do a regular index build in a transaction
BEGIN;
CREATE INDEX std_index on concur_heap(f2);
diff --git a/src/test/regress/sql/create_index.sql b/src/test/regress/sql/create_index.sql
index c0392f052d..71779e3dce 100644
--- a/src/test/regress/sql/create_index.sql
+++ b/src/test/regress/sql/create_index.sql
@@ -487,6 +487,19 @@ BEGIN;
CREATE INDEX CONCURRENTLY concur_index7 ON concur_heap(f1);
COMMIT;
+CREATE FUNCTION predicate() RETURNS bool IMMUTABLE LANGUAGE plpgsql AS $$
+BEGIN
+ EXECUTE 'SELECT txid_current()';
+ RETURN true;
+END; $$;
+
+-- You can't do any transactional updates during concurrent index build.
+CREATE INDEX CONCURRENTLY concur_index8 ON concur_heap (f1) WHERE predicate();
+-- Index exists but invalid. It must be actualized after REINDEX TABLE command.
+SELECT relname,indisvalid FROM pg_class, pg_index
+ WHERE relname = 'concur_index8' AND oid = indexrelid;
+DROP INDEX concur_index8;
+
-- But you can do a regular index build in a transaction
BEGIN;
CREATE INDEX std_index on concur_heap(f2);
--
2.31.1