mirror of
https://github.com/postgres/postgres.git
synced 2025-06-25 01:02:05 +03:00
Fix failure to handle conflicts in non-arbiter exclusion constraints.
ExecInsertIndexTuples treated an exclusion constraint as subject to noDupErr processing even when it was not listed in arbiterIndexes, and would therefore not error out for a conflict in such a constraint, instead returning it as an arbiter-index failure. That led to an infinite loop in ExecInsert, since ExecCheckIndexConstraints ignored the index as-intended and therefore didn't throw the expected error. To fix, make the exclusion constraint code path use the same condition as the index_insert call does to decide whether no-error-for-duplicates behavior is appropriate. While at it, refactor a little bit to avoid unnecessary list_member_oid calls. (That surely wouldn't save anything worth noticing, but I find the code a bit clearer this way.) Per bug report from Heikki Rauhala. Back-patch to 9.5 where ON CONFLICT was introduced. Report: <4C976D6B-76B4-434C-8052-D009F7B7AEDA@reaktor.fi>
This commit is contained in:
@ -704,3 +704,26 @@ insert into dropcol(key, keep1, keep2) values(1, '5', 5) on conflict(key)
|
||||
|
||||
;
|
||||
DROP TABLE dropcol;
|
||||
-- check handling of regular btree constraint along with gist constraint
|
||||
create table twoconstraints (f1 int unique, f2 box,
|
||||
exclude using gist(f2 with &&));
|
||||
insert into twoconstraints values(1, '((0,0),(1,1))');
|
||||
insert into twoconstraints values(1, '((2,2),(3,3))'); -- fail on f1
|
||||
ERROR: duplicate key value violates unique constraint "twoconstraints_f1_key"
|
||||
DETAIL: Key (f1)=(1) already exists.
|
||||
insert into twoconstraints values(2, '((0,0),(1,2))'); -- fail on f2
|
||||
ERROR: conflicting key value violates exclusion constraint "twoconstraints_f2_excl"
|
||||
DETAIL: Key (f2)=((1,2),(0,0)) conflicts with existing key (f2)=((1,1),(0,0)).
|
||||
insert into twoconstraints values(2, '((0,0),(1,2))')
|
||||
on conflict on constraint twoconstraints_f1_key do nothing; -- fail on f2
|
||||
ERROR: conflicting key value violates exclusion constraint "twoconstraints_f2_excl"
|
||||
DETAIL: Key (f2)=((1,2),(0,0)) conflicts with existing key (f2)=((1,1),(0,0)).
|
||||
insert into twoconstraints values(2, '((0,0),(1,2))')
|
||||
on conflict on constraint twoconstraints_f2_excl do nothing; -- do nothing
|
||||
select * from twoconstraints;
|
||||
f1 | f2
|
||||
----+-------------
|
||||
1 | (1,1),(0,0)
|
||||
(1 row)
|
||||
|
||||
drop table twoconstraints;
|
||||
|
@ -407,3 +407,17 @@ insert into dropcol(key, keep1, keep2) values(1, '5', 5) on conflict(key)
|
||||
;
|
||||
|
||||
DROP TABLE dropcol;
|
||||
|
||||
-- check handling of regular btree constraint along with gist constraint
|
||||
|
||||
create table twoconstraints (f1 int unique, f2 box,
|
||||
exclude using gist(f2 with &&));
|
||||
insert into twoconstraints values(1, '((0,0),(1,1))');
|
||||
insert into twoconstraints values(1, '((2,2),(3,3))'); -- fail on f1
|
||||
insert into twoconstraints values(2, '((0,0),(1,2))'); -- fail on f2
|
||||
insert into twoconstraints values(2, '((0,0),(1,2))')
|
||||
on conflict on constraint twoconstraints_f1_key do nothing; -- fail on f2
|
||||
insert into twoconstraints values(2, '((0,0),(1,2))')
|
||||
on conflict on constraint twoconstraints_f2_excl do nothing; -- do nothing
|
||||
select * from twoconstraints;
|
||||
drop table twoconstraints;
|
||||
|
Reference in New Issue
Block a user