mirror of
https://github.com/postgres/postgres.git
synced 2025-11-19 13:42:17 +03:00
Add UNIQUE null treatment option
The SQL standard has been ambiguous about whether null values in
unique constraints should be considered equal or not. Different
implementations have different behaviors. In the SQL:202x draft, this
has been formalized by making this implementation-defined and adding
an option on unique constraint definitions UNIQUE [ NULLS [NOT]
DISTINCT ] to choose a behavior explicitly.
This patch adds this option to PostgreSQL. The default behavior
remains UNIQUE NULLS DISTINCT. Making this happen in the btree code
is pretty easy; most of the patch is just to carry the flag around to
all the places that need it.
The CREATE UNIQUE INDEX syntax extension is not from the standard,
it's my own invention.
I named all the internal flags, catalog columns, etc. in the negative
("nulls not distinct") so that the default PostgreSQL behavior is the
default if the flag is false.
Reviewed-by: Maxim Orlov <orlovmg@gmail.com>
Reviewed-by: Pavel Borisov <pashkin.elfe@gmail.com>
Discussion: https://www.postgresql.org/message-id/flat/84e5ee1b-387e-9a54-c326-9082674bde78@enterprisedb.com
This commit is contained in:
@@ -459,6 +459,7 @@ struct Tuplesortstate
|
||||
|
||||
/* These are specific to the index_btree subcase: */
|
||||
bool enforceUnique; /* complain if we find duplicate tuples */
|
||||
bool uniqueNullsNotDistinct; /* unique constraint null treatment */
|
||||
|
||||
/* These are specific to the index_hash subcase: */
|
||||
uint32 high_mask; /* masks for sortable part of hash code */
|
||||
@@ -1065,6 +1066,7 @@ Tuplesortstate *
|
||||
tuplesort_begin_index_btree(Relation heapRel,
|
||||
Relation indexRel,
|
||||
bool enforceUnique,
|
||||
bool uniqueNullsNotDistinct,
|
||||
int workMem,
|
||||
SortCoordinate coordinate,
|
||||
bool randomAccess)
|
||||
@@ -1103,6 +1105,7 @@ tuplesort_begin_index_btree(Relation heapRel,
|
||||
state->heapRel = heapRel;
|
||||
state->indexRel = indexRel;
|
||||
state->enforceUnique = enforceUnique;
|
||||
state->uniqueNullsNotDistinct = uniqueNullsNotDistinct;
|
||||
|
||||
indexScanKey = _bt_mkscankey(indexRel, NULL);
|
||||
|
||||
@@ -4200,14 +4203,15 @@ comparetup_index_btree(const SortTuple *a, const SortTuple *b,
|
||||
|
||||
/*
|
||||
* If btree has asked us to enforce uniqueness, complain if two equal
|
||||
* tuples are detected (unless there was at least one NULL field).
|
||||
* tuples are detected (unless there was at least one NULL field and NULLS
|
||||
* NOT DISTINCT was not set).
|
||||
*
|
||||
* It is sufficient to make the test here, because if two tuples are equal
|
||||
* they *must* get compared at some stage of the sort --- otherwise the
|
||||
* sort algorithm wouldn't have checked whether one must appear before the
|
||||
* other.
|
||||
*/
|
||||
if (state->enforceUnique && !equal_hasnull)
|
||||
if (state->enforceUnique && !(!state->uniqueNullsNotDistinct && equal_hasnull))
|
||||
{
|
||||
Datum values[INDEX_MAX_KEYS];
|
||||
bool isnull[INDEX_MAX_KEYS];
|
||||
|
||||
Reference in New Issue
Block a user