Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit31ce32a

Browse files
committed
Fix failure to handle conflicts in non-arbiter exclusion constraints.
ExecInsertIndexTuples treated an exclusion constraint as subject tonoDupErr processing even when it was not listed in arbiterIndexes, andwould therefore not error out for a conflict in such a constraint, insteadreturning it as an arbiter-index failure. That led to an infinite loop inExecInsert, since ExecCheckIndexConstraints ignored the index as-intendedand therefore didn't throw the expected error. To fix, make the exclusionconstraint code path use the same condition as the index_insert call doesto decide whether no-error-for-duplicates behavior is appropriate. Whileat it, refactor a little bit to avoid unnecessary list_member_oid calls.(That surely wouldn't save anything worth noticing, but I find the codea bit clearer this way.)Per bug report from Heikki Rauhala. Back-patch to 9.5 where ON CONFLICTwas introduced.Report: <4C976D6B-76B4-434C-8052-D009F7B7AEDA@reaktor.fi>
1 parente612181 commit31ce32a

File tree

3 files changed

+49
-7
lines changed

3 files changed

+49
-7
lines changed

‎src/backend/executor/execIndexing.c

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,9 @@ ExecCloseIndices(ResultRelInfo *resultRelInfo)
259259
*the same is done for non-deferred constraints, but report
260260
*if conflict was speculative or deferred conflict to caller)
261261
*
262+
*If 'arbiterIndexes' is nonempty, noDupErr applies only to
263+
*those indexes. NIL means noDupErr applies to all indexes.
264+
*
262265
*CAUTION: this must not be called for a HOT update.
263266
*We can't defend against that here for lack of info.
264267
*Should we change the API to make it safer?
@@ -308,19 +311,15 @@ ExecInsertIndexTuples(TupleTableSlot *slot,
308311
{
309312
RelationindexRelation=relationDescs[i];
310313
IndexInfo*indexInfo;
314+
boolapplyNoDupErr;
311315
IndexUniqueCheckcheckUnique;
312316
boolsatisfiesConstraint;
313-
boolarbiter;
314317

315318
if (indexRelation==NULL)
316319
continue;
317320

318321
indexInfo=indexInfoArray[i];
319322

320-
/* Record if speculative insertion arbiter */
321-
arbiter=list_member_oid(arbiterIndexes,
322-
indexRelation->rd_index->indexrelid);
323-
324323
/* If the index is marked as read-only, ignore it */
325324
if (!indexInfo->ii_ReadyForInserts)
326325
continue;
@@ -358,6 +357,12 @@ ExecInsertIndexTuples(TupleTableSlot *slot,
358357
values,
359358
isnull);
360359

360+
/* Check whether to apply noDupErr to this index */
361+
applyNoDupErr=noDupErr&&
362+
(arbiterIndexes==NIL||
363+
list_member_oid(arbiterIndexes,
364+
indexRelation->rd_index->indexrelid));
365+
361366
/*
362367
* The index AM does the actual insertion, plus uniqueness checking.
363368
*
@@ -373,7 +378,7 @@ ExecInsertIndexTuples(TupleTableSlot *slot,
373378
*/
374379
if (!indexRelation->rd_index->indisunique)
375380
checkUnique=UNIQUE_CHECK_NO;
376-
elseif (noDupErr&& (arbiterIndexes==NIL||arbiter))
381+
elseif (applyNoDupErr)
377382
checkUnique=UNIQUE_CHECK_PARTIAL;
378383
elseif (indexRelation->rd_index->indimmediate)
379384
checkUnique=UNIQUE_CHECK_YES;
@@ -407,7 +412,7 @@ ExecInsertIndexTuples(TupleTableSlot *slot,
407412
boolviolationOK;
408413
CEOUC_WAIT_MODEwaitMode;
409414

410-
if (noDupErr)
415+
if (applyNoDupErr)
411416
{
412417
violationOK= true;
413418
waitMode=CEOUC_LIVELOCK_PREVENTING_WAIT;

‎src/test/regress/expected/insert_conflict.out

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -702,3 +702,26 @@ insert into dropcol(key, keep1, keep2) values(1, '5', 5) on conflict(key)
702702

703703
;
704704
DROP TABLE dropcol;
705+
-- check handling of regular btree constraint along with gist constraint
706+
create table twoconstraints (f1 int unique, f2 box,
707+
exclude using gist(f2 with &&));
708+
insert into twoconstraints values(1, '((0,0),(1,1))');
709+
insert into twoconstraints values(1, '((2,2),(3,3))'); -- fail on f1
710+
ERROR: duplicate key value violates unique constraint "twoconstraints_f1_key"
711+
DETAIL: Key (f1)=(1) already exists.
712+
insert into twoconstraints values(2, '((0,0),(1,2))'); -- fail on f2
713+
ERROR: conflicting key value violates exclusion constraint "twoconstraints_f2_excl"
714+
DETAIL: Key (f2)=((1,2),(0,0)) conflicts with existing key (f2)=((1,1),(0,0)).
715+
insert into twoconstraints values(2, '((0,0),(1,2))')
716+
on conflict on constraint twoconstraints_f1_key do nothing; -- fail on f2
717+
ERROR: conflicting key value violates exclusion constraint "twoconstraints_f2_excl"
718+
DETAIL: Key (f2)=((1,2),(0,0)) conflicts with existing key (f2)=((1,1),(0,0)).
719+
insert into twoconstraints values(2, '((0,0),(1,2))')
720+
on conflict on constraint twoconstraints_f2_excl do nothing; -- do nothing
721+
select * from twoconstraints;
722+
f1 | f2
723+
----+-------------
724+
1 | (1,1),(0,0)
725+
(1 row)
726+
727+
drop table twoconstraints;

‎src/test/regress/sql/insert_conflict.sql

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,3 +407,17 @@ insert into dropcol(key, keep1, keep2) values(1, '5', 5) on conflict(key)
407407
;
408408

409409
DROPTABLE dropcol;
410+
411+
-- check handling of regular btree constraint along with gist constraint
412+
413+
createtabletwoconstraints (f1int unique, f2box,
414+
exclude using gist(f2 with &&));
415+
insert into twoconstraintsvalues(1,'((0,0),(1,1))');
416+
insert into twoconstraintsvalues(1,'((2,2),(3,3))');-- fail on f1
417+
insert into twoconstraintsvalues(2,'((0,0),(1,2))');-- fail on f2
418+
insert into twoconstraintsvalues(2,'((0,0),(1,2))')
419+
on conflictonconstraint twoconstraints_f1_key do nothing;-- fail on f2
420+
insert into twoconstraintsvalues(2,'((0,0),(1,2))')
421+
on conflictonconstraint twoconstraints_f2_excl do nothing;-- do nothing
422+
select*from twoconstraints;
423+
droptable twoconstraints;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp