mirror of
https://github.com/postgres/postgres.git
synced 2025-07-05 07:21:24 +03:00
Fix incorrect checking of deferred exclusion constraint after a HOT update.
If a row that potentially violates a deferred exclusion constraint is HOT-updated later in the same transaction, the exclusion constraint would be reported as violated when the check finally occurs, even if the row(s) the new row originally conflicted with have since been removed. This happened because the wrong TID was passed to check_exclusion_constraint(), causing the live HOT-updated row to be seen as a conflicting row rather than recognized as the row-under-test. Per bug #13148 from Evan Martin. It's been broken since exclusion constraints were invented, so back-patch to all supported branches.
This commit is contained in:
@ -467,6 +467,7 @@ DROP TABLE circles;
|
||||
|
||||
CREATE TABLE deferred_excl (
|
||||
f1 int,
|
||||
f2 int,
|
||||
CONSTRAINT deferred_excl_con EXCLUDE (f1 WITH =) INITIALLY DEFERRED
|
||||
);
|
||||
|
||||
@ -482,6 +483,15 @@ INSERT INTO deferred_excl VALUES(3);
|
||||
INSERT INTO deferred_excl VALUES(3); -- no fail here
|
||||
COMMIT; -- should fail here
|
||||
|
||||
-- bug #13148: deferred constraint versus HOT update
|
||||
BEGIN;
|
||||
INSERT INTO deferred_excl VALUES(2, 1); -- no fail here
|
||||
DELETE FROM deferred_excl WHERE f1 = 2 AND f2 IS NULL; -- remove old row
|
||||
UPDATE deferred_excl SET f2 = 2 WHERE f1 = 2;
|
||||
COMMIT; -- should not fail
|
||||
|
||||
SELECT * FROM deferred_excl;
|
||||
|
||||
ALTER TABLE deferred_excl DROP CONSTRAINT deferred_excl_con;
|
||||
|
||||
-- This should fail, but worth testing because of HOT updates
|
||||
|
@ -634,6 +634,7 @@ DROP TABLE circles;
|
||||
-- Check deferred exclusion constraint
|
||||
CREATE TABLE deferred_excl (
|
||||
f1 int,
|
||||
f2 int,
|
||||
CONSTRAINT deferred_excl_con EXCLUDE (f1 WITH =) INITIALLY DEFERRED
|
||||
);
|
||||
INSERT INTO deferred_excl VALUES(1);
|
||||
@ -654,6 +655,19 @@ INSERT INTO deferred_excl VALUES(3); -- no fail here
|
||||
COMMIT; -- should fail here
|
||||
ERROR: conflicting key value violates exclusion constraint "deferred_excl_con"
|
||||
DETAIL: Key (f1)=(3) conflicts with existing key (f1)=(3).
|
||||
-- bug #13148: deferred constraint versus HOT update
|
||||
BEGIN;
|
||||
INSERT INTO deferred_excl VALUES(2, 1); -- no fail here
|
||||
DELETE FROM deferred_excl WHERE f1 = 2 AND f2 IS NULL; -- remove old row
|
||||
UPDATE deferred_excl SET f2 = 2 WHERE f1 = 2;
|
||||
COMMIT; -- should not fail
|
||||
SELECT * FROM deferred_excl;
|
||||
f1 | f2
|
||||
----+----
|
||||
1 |
|
||||
2 | 2
|
||||
(2 rows)
|
||||
|
||||
ALTER TABLE deferred_excl DROP CONSTRAINT deferred_excl_con;
|
||||
-- This should fail, but worth testing because of HOT updates
|
||||
UPDATE deferred_excl SET f1 = 3;
|
||||
|
Reference in New Issue
Block a user