Fix check_exclusion_or_unique_constraint for UNIQUE NULLS NOT DISTINCT.
Adjusting this function was overlooked in commit 94aa7cc5f
. The only
visible symptom (so far) is that INSERT ... ON CONFLICT could go into
an endless loop when inserting a null that has a conflict.
Richard Guo and Tom Lane, per bug #17558 from Andrew Kesper
Discussion: https://postgr.es/m/17558-3f6599ffcf52fd4a@postgresql.org
This commit is contained in:
parent
4c7b16312e
commit
3419d51e19
|
@ -699,14 +699,20 @@ check_exclusion_or_unique_constraint(Relation heap, Relation index,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If any of the input values are NULL, the constraint check is assumed to
|
* If any of the input values are NULL, and the index uses the default
|
||||||
* pass (i.e., we assume the operators are strict).
|
* nulls-are-distinct mode, the constraint check is assumed to pass (i.e.,
|
||||||
|
* we assume the operators are strict). Otherwise, we interpret the
|
||||||
|
* constraint as specifying IS NULL for each column whose input value is
|
||||||
|
* NULL.
|
||||||
*/
|
*/
|
||||||
|
if (!indexInfo->ii_NullsNotDistinct)
|
||||||
|
{
|
||||||
for (i = 0; i < indnkeyatts; i++)
|
for (i = 0; i < indnkeyatts; i++)
|
||||||
{
|
{
|
||||||
if (isnull[i])
|
if (isnull[i])
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Search the tuples that are in the index for any violations, including
|
* Search the tuples that are in the index for any violations, including
|
||||||
|
@ -717,7 +723,7 @@ check_exclusion_or_unique_constraint(Relation heap, Relation index,
|
||||||
for (i = 0; i < indnkeyatts; i++)
|
for (i = 0; i < indnkeyatts; i++)
|
||||||
{
|
{
|
||||||
ScanKeyEntryInitialize(&scankeys[i],
|
ScanKeyEntryInitialize(&scankeys[i],
|
||||||
0,
|
isnull[i] ? SK_ISNULL | SK_SEARCHNULL : 0,
|
||||||
i + 1,
|
i + 1,
|
||||||
constr_strats[i],
|
constr_strats[i],
|
||||||
InvalidOid,
|
InvalidOid,
|
||||||
|
|
|
@ -449,15 +449,16 @@ DROP TABLE UNIQUE_TBL;
|
||||||
CREATE TABLE UNIQUE_TBL (i int UNIQUE NULLS NOT DISTINCT, t text);
|
CREATE TABLE UNIQUE_TBL (i int UNIQUE NULLS NOT DISTINCT, t text);
|
||||||
INSERT INTO UNIQUE_TBL VALUES (1, 'one');
|
INSERT INTO UNIQUE_TBL VALUES (1, 'one');
|
||||||
INSERT INTO UNIQUE_TBL VALUES (2, 'two');
|
INSERT INTO UNIQUE_TBL VALUES (2, 'two');
|
||||||
INSERT INTO UNIQUE_TBL VALUES (1, 'three');
|
INSERT INTO UNIQUE_TBL VALUES (1, 'three'); -- fail
|
||||||
ERROR: duplicate key value violates unique constraint "unique_tbl_i_key"
|
ERROR: duplicate key value violates unique constraint "unique_tbl_i_key"
|
||||||
DETAIL: Key (i)=(1) already exists.
|
DETAIL: Key (i)=(1) already exists.
|
||||||
INSERT INTO UNIQUE_TBL VALUES (4, 'four');
|
INSERT INTO UNIQUE_TBL VALUES (4, 'four');
|
||||||
INSERT INTO UNIQUE_TBL VALUES (5, 'one');
|
INSERT INTO UNIQUE_TBL VALUES (5, 'one');
|
||||||
INSERT INTO UNIQUE_TBL (t) VALUES ('six');
|
INSERT INTO UNIQUE_TBL (t) VALUES ('six');
|
||||||
INSERT INTO UNIQUE_TBL (t) VALUES ('seven');
|
INSERT INTO UNIQUE_TBL (t) VALUES ('seven'); -- fail
|
||||||
ERROR: duplicate key value violates unique constraint "unique_tbl_i_key"
|
ERROR: duplicate key value violates unique constraint "unique_tbl_i_key"
|
||||||
DETAIL: Key (i)=(null) already exists.
|
DETAIL: Key (i)=(null) already exists.
|
||||||
|
INSERT INTO UNIQUE_TBL (t) VALUES ('eight') ON CONFLICT DO NOTHING; -- no-op
|
||||||
SELECT * FROM UNIQUE_TBL;
|
SELECT * FROM UNIQUE_TBL;
|
||||||
i | t
|
i | t
|
||||||
---+------
|
---+------
|
||||||
|
|
|
@ -310,11 +310,12 @@ CREATE TABLE UNIQUE_TBL (i int UNIQUE NULLS NOT DISTINCT, t text);
|
||||||
|
|
||||||
INSERT INTO UNIQUE_TBL VALUES (1, 'one');
|
INSERT INTO UNIQUE_TBL VALUES (1, 'one');
|
||||||
INSERT INTO UNIQUE_TBL VALUES (2, 'two');
|
INSERT INTO UNIQUE_TBL VALUES (2, 'two');
|
||||||
INSERT INTO UNIQUE_TBL VALUES (1, 'three');
|
INSERT INTO UNIQUE_TBL VALUES (1, 'three'); -- fail
|
||||||
INSERT INTO UNIQUE_TBL VALUES (4, 'four');
|
INSERT INTO UNIQUE_TBL VALUES (4, 'four');
|
||||||
INSERT INTO UNIQUE_TBL VALUES (5, 'one');
|
INSERT INTO UNIQUE_TBL VALUES (5, 'one');
|
||||||
INSERT INTO UNIQUE_TBL (t) VALUES ('six');
|
INSERT INTO UNIQUE_TBL (t) VALUES ('six');
|
||||||
INSERT INTO UNIQUE_TBL (t) VALUES ('seven');
|
INSERT INTO UNIQUE_TBL (t) VALUES ('seven'); -- fail
|
||||||
|
INSERT INTO UNIQUE_TBL (t) VALUES ('eight') ON CONFLICT DO NOTHING; -- no-op
|
||||||
|
|
||||||
SELECT * FROM UNIQUE_TBL;
|
SELECT * FROM UNIQUE_TBL;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue