summaryrefslogtreecommitdiff
path: root/src/test
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2016-10-23 15:01:24 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2016-10-23 15:01:24 -0400
commitd4fa18a551a11a4193bbe91d691952a82549bafc (patch)
treec3c4cf860e9f95b9caeb2710afe80cfeeaf31ac7 /src/test
parent24542e253555eea619e7cdf66ac107e59c70a10e (diff)
Avoid testing tuple visibility without buffer lock in RI_FKey_check().
Despite the argumentation I wrote in commit 7a2fe85b0, it's unsafe to do this, because in corner cases it's possible for HeapTupleSatisfiesSelf to try to set hint bits on the target tuple; and at least since 8.2 we have required the buffer content lock to be held while setting hint bits. The added regression test exercises one such corner case. Unpatched, it causes an assertion failure in assert-enabled builds, or otherwise would cause a hint bit change in a buffer we don't hold lock on, which given the right race condition could result in checksum failures or other data consistency problems. The odds of a problem in the field are probably pretty small, but nonetheless back-patch to all supported branches. Report: <19391.1477244876@sss.pgh.pa.us>
Diffstat (limited to 'src/test')
-rw-r--r--src/test/regress/expected/foreign_key.out22
-rw-r--r--src/test/regress/sql/foreign_key.sql23
2 files changed, 45 insertions, 0 deletions
diff --git a/src/test/regress/expected/foreign_key.out b/src/test/regress/expected/foreign_key.out
index 65dfe024a99..de829d71599 100644
--- a/src/test/regress/expected/foreign_key.out
+++ b/src/test/regress/expected/foreign_key.out
@@ -1319,3 +1319,25 @@ begin;
(2 rows)
commit;
+--
+-- Test deferred FK check on a tuple deleted by a rolled-back subtransaction
+--
+create table pktable2(f1 int primary key);
+NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "pktable2_pkey" for table "pktable2"
+create table fktable2(f1 int references pktable2 deferrable initially deferred);
+insert into pktable2 values(1);
+begin;
+insert into fktable2 values(1);
+savepoint x;
+delete from fktable2;
+rollback to x;
+commit;
+begin;
+insert into fktable2 values(2);
+savepoint x;
+delete from fktable2;
+rollback to x;
+commit; -- fail
+ERROR: insert or update on table "fktable2" violates foreign key constraint "fktable2_f1_fkey"
+DETAIL: Key (f1)=(2) is not present in table "pktable2".
+drop table pktable2, fktable2;
diff --git a/src/test/regress/sql/foreign_key.sql b/src/test/regress/sql/foreign_key.sql
index 6bd9ddd1a5e..c81c737c5c9 100644
--- a/src/test/regress/sql/foreign_key.sql
+++ b/src/test/regress/sql/foreign_key.sql
@@ -943,3 +943,26 @@ begin;
update selfref set a = 456 where a = 123;
select a, b from selfref;
commit;
+
+--
+-- Test deferred FK check on a tuple deleted by a rolled-back subtransaction
+--
+create table pktable2(f1 int primary key);
+create table fktable2(f1 int references pktable2 deferrable initially deferred);
+insert into pktable2 values(1);
+
+begin;
+insert into fktable2 values(1);
+savepoint x;
+delete from fktable2;
+rollback to x;
+commit;
+
+begin;
+insert into fktable2 values(2);
+savepoint x;
+delete from fktable2;
+rollback to x;
+commit; -- fail
+
+drop table pktable2, fktable2;