summaryrefslogtreecommitdiff
path: root/src/test
diff options
context:
space:
mode:
authorNoah Misch <noah@leadboat.com>2024-10-25 06:51:02 -0700
committerNoah Misch <noah@leadboat.com>2024-10-25 06:51:07 -0700
commit4eac5a1fa78edde0de53a89bd2b06e1fe5588913 (patch)
treec0eda5bc9fbc69c2a79dcdf88741ea23bd04f62f /src/test
parent3baf804b7295fff7551f93ed94550d8268804cc1 (diff)
For inplace update, send nontransactional invalidations.
The inplace update survives ROLLBACK. The inval didn't, so another backend's DDL could then update the row without incorporating the inplace update. In the test this fixes, a mix of CREATE INDEX and ALTER TABLE resulted in a table with an index, yet relhasindex=f. That is a source of index corruption. Back-patch to v12 (all supported versions). The back branch versions don't change WAL, because those branches just added end-of-recovery SIResetAll(). All branches change the ABI of extern function PrepareToInvalidateCacheTuple(). No PGXN extension calls that, and there's no apparent use case in extensions. Reviewed by Nitin Motiani and (in earlier versions) Andres Freund. Discussion: https://postgr.es/m/20240523000548.58.nmisch@google.com
Diffstat (limited to 'src/test')
-rw-r--r--src/test/isolation/expected/inplace-inval.out10
-rw-r--r--src/test/isolation/specs/inplace-inval.spec12
2 files changed, 14 insertions, 8 deletions
diff --git a/src/test/isolation/expected/inplace-inval.out b/src/test/isolation/expected/inplace-inval.out
index e68eca5de98..c35895a8aa7 100644
--- a/src/test/isolation/expected/inplace-inval.out
+++ b/src/test/isolation/expected/inplace-inval.out
@@ -1,6 +1,6 @@
Parsed test spec with 3 sessions
-starting permutation: cachefill3 cir1 cic2 ddl3
+starting permutation: cachefill3 cir1 cic2 ddl3 read1
step cachefill3: TABLE newly_indexed;
c
-
@@ -9,6 +9,14 @@ c
step cir1: BEGIN; CREATE INDEX i1 ON newly_indexed (c); ROLLBACK;
step cic2: CREATE INDEX i2 ON newly_indexed (c);
step ddl3: ALTER TABLE newly_indexed ADD extra int;
+step read1:
+ SELECT relhasindex FROM pg_class WHERE oid = 'newly_indexed'::regclass;
+
+relhasindex
+-----------
+t
+(1 row)
+
starting permutation: cir1 cic2 ddl3 read1
step cir1: BEGIN; CREATE INDEX i1 ON newly_indexed (c); ROLLBACK;
diff --git a/src/test/isolation/specs/inplace-inval.spec b/src/test/isolation/specs/inplace-inval.spec
index 96954fd86c4..b99112ddb88 100644
--- a/src/test/isolation/specs/inplace-inval.spec
+++ b/src/test/isolation/specs/inplace-inval.spec
@@ -1,7 +1,7 @@
-# If a heap_update() caller retrieves its oldtup from a cache, it's possible
-# for that cache entry to predate an inplace update, causing loss of that
-# inplace update. This arises because the transaction may abort before
-# sending the inplace invalidation message to the shared queue.
+# An inplace update had been able to abort before sending the inplace
+# invalidation message to the shared queue. If a heap_update() caller then
+# retrieved its oldtup from a cache, the heap_update() could revert the
+# inplace update.
setup
{
@@ -27,14 +27,12 @@ step cachefill3 { TABLE newly_indexed; }
step ddl3 { ALTER TABLE newly_indexed ADD extra int; }
-# XXX shows an extant bug. Adding step read1 at the end would usually print
-# relhasindex=f (not wanted). This does not reach the unwanted behavior under
-# -DCATCACHE_FORCE_RELEASE and friends.
permutation
cachefill3 # populates the pg_class row in the catcache
cir1 # sets relhasindex=true; rollback discards cache inval
cic2 # sees relhasindex=true, skips changing it (so no inval)
ddl3 # cached row as the oldtup of an update, losing relhasindex
+ read1 # observe damage
# without cachefill3, no bug
permutation cir1 cic2 ddl3 read1