Skip to content

Commit

Permalink
opt: support UPDATE with partial UNIQUE WITHOUT INDEX constraints
Browse files Browse the repository at this point in the history
This commit add uniqueness checks for partial `UNIQUE WITHOUT INDEX`
constraints during `UPDATE` statements.

As partial of this change, I discovered that #60535 introduced a
regression where columns not required by uniqueness checks are not
pruned. I've left TODOs in the column pruning tests and plan on fixing
this in a follow-up PR.

There is no release note because these constraints are gated behind the
experimental_enable_unique_without_index_constraints session variable.

Release note: None
  • Loading branch information
mgartner committed Feb 20, 2021
1 parent 8b6f3c8 commit b5cc909
Show file tree
Hide file tree
Showing 6 changed files with 1,027 additions and 91 deletions.
61 changes: 51 additions & 10 deletions pkg/sql/logictest/testdata/logic_test/unique
Original file line number Diff line number Diff line change
Expand Up @@ -86,13 +86,6 @@ CREATE TABLE uniq_enum (
UNIQUE WITHOUT INDEX (s, j)
)

statement ok
CREATE TABLE uniq_partial_index (
i INT,
UNIQUE WITHOUT INDEX (i),
UNIQUE INDEX (i) WHERE i > 0
)

statement ok
CREATE TABLE other (k INT, v INT, w INT NOT NULL, x INT, y INT)

Expand Down Expand Up @@ -437,6 +430,47 @@ r s i j
eu-west bar 2 2
us-west foo 1 1

# Set a to the same value it already has.
statement ok
UPDATE uniq_partial SET a = 1 WHERE a = 1 AND b = 1

# Set a to an existing value.
statement error pgcode 23505 pq: duplicate key value violates unique constraint "unique_a"\nDETAIL: Key \(a\)=\(1\) already exists\.
UPDATE uniq_partial SET a = 1 WHERE a = 2

# Make b of (1, -1) positive so that it conflicts with (1, 1)
statement error pgcode 23505 pq: duplicate key value violates unique constraint "unique_a"\nDETAIL: Key \(a\)=\(1\) already exists\.
UPDATE uniq_partial SET b = 10 WHERE a = 1 AND b = -1

# Set a to NULL.
statement ok
UPDATE uniq_partial SET a = NULL, b = 10 WHERE a = 1 AND b = -1

# Update two existing, non-conflicting rows resulting in a conflict.
statement error pgcode 23505 pq: duplicate key value violates unique constraint "unique_a"\nDETAIL: Key \(a\)=\(10\) already exists\.
UPDATE uniq_partial SET a = 10 WHERE a IS NULL AND b = 5

# Set a to a non-existing value.
statement ok
UPDATE uniq_partial SET a = 10 WHERE a = 9 AND b = 9

query II colnames,rowsort
SELECT * FROM uniq_partial
----
a b
1 1
1 -3
2 2
5 5
6 6
7 7
7 -7
9 -9
10 9
NULL 5
NULL 5
NULL 10


# -- Tests with UPSERT --
subtest Upsert
Expand Down Expand Up @@ -616,11 +650,18 @@ eu-west bar 2 2
# Ensure that we do not choose a partial index as the arbiter when there is a
# UNIQUE WITHOUT INDEX constraint.
statement ok
INSERT INTO uniq_partial_index VALUES (-1) ON CONFLICT (i) WHERE i > 0 DO UPDATE SET i = 1;
INSERT INTO uniq_partial_index VALUES (-1) ON CONFLICT (i) WHERE i > 0 DO UPDATE SET i = 2
CREATE TABLE uniq_partial_index_and_constraint (
i INT,
UNIQUE WITHOUT INDEX (i),
UNIQUE INDEX (i) WHERE i > 0
)

statement ok
INSERT INTO uniq_partial_index_and_constraint VALUES (-1) ON CONFLICT (i) WHERE i > 0 DO UPDATE SET i = 1;
INSERT INTO uniq_partial_index_and_constraint VALUES (-1) ON CONFLICT (i) WHERE i > 0 DO UPDATE SET i = 2

query I colnames
SELECT * FROM uniq_partial_index
SELECT * FROM uniq_partial_index_and_constraint
----
i
2
Expand Down
Loading

0 comments on commit b5cc909

Please sign in to comment.