Skip to content

Commit

Permalink
Merge #58053
Browse files Browse the repository at this point in the history
58053: opt, sql: add end-to-end support for uniqueness checks r=rytaft a=rytaft

**opt: generalize explain output for constraint checks**

This commit changes the explain output for constraint checks to
say "constraint-check" rather than "fk-check" so that it can be used
for uniqueness checks in addition to foreign key checks.

Release note (sql change): The explain output for foreign key checks
is now labeled constraint-check rather than fk-check. This change
is in preparation for adding support for unique constraint checks,
which will use the same label.

**sql: update unique violation error to be Postgres compatible**

This commit fixes the violation error for unique constraints to match
the message used by Postres. Previously, the error would have been
printed as:

`duplicate key value (k)=(1) violates unique constraint "primary"`

Now this message is printed as:
```
ERROR:  duplicate key value violates unique constraint "primary"
DETAIL: Key (k)=(1) already exists.
```
Release note (sql change): The error message for unique constraint
violations now matches the error used by Postgres. For example,
the new error message looks like this:
ERROR:   duplicate key value violates unique constraint "primary"
DETAIL: Key (k)=(1) already exists.

**opt: add end-to-end support for uniqueness checks**

This commit updates the `execbuilder` to build uniqueness checks for
insert and update queries when needed. It also fixes a few other bugs
in the existing code that were preventing the checks from being built.
As of this commit, uniqueness checks for insert and update now work
end-to-end. This commit also includes a number of `execbuilder` and logic
tests for uniqueness checks.

There is no release note since these checks are still gated behind the
`experimental_enable_unique_without_index_constraints` session variable.

Informs #41535

Release note: None

Co-authored-by: Rebecca Taft <[email protected]>
  • Loading branch information
craig[bot] and rytaft committed Dec 21, 2020
2 parents 25eb03d + 20a5a9b commit 862edb7
Show file tree
Hide file tree
Showing 32 changed files with 1,270 additions and 103 deletions.
2 changes: 1 addition & 1 deletion pkg/sql/logictest/testdata/logic_test/alter_table
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ ALTER TABLE t ADD d INT UNIQUE
statement ok
INSERT INTO t VALUES (4, 9, 1)

statement error duplicate key value \(d\)=\(1\) violates unique constraint \"t_d_key\"
statement error duplicate key value violates unique constraint \"t_d_key\"\nDETAIL: Key \(d\)=\(1\) already exists\.
INSERT INTO t VALUES (5, 9, 1)

# Add a column with no default value
Expand Down
2 changes: 1 addition & 1 deletion pkg/sql/logictest/testdata/logic_test/array
Original file line number Diff line number Diff line change
Expand Up @@ -1362,7 +1362,7 @@ INSERT INTO t VALUES

# Test that the unique index rejects bad inserts.
# Disabled until #50659 is resolved.
#statement error pq: duplicate key value \(x\)=\(ARRAY\[1,NULL,10\]\) violates unique constraint "primary"
#statement error pq: duplicate key value violates unique constraint "primary"\nDETAIL: Key \(x\)=\(ARRAY\[1,NULL,10\]\) already exists\.
#INSERT INTO t VALUES (ARRAY[1, NULL, 10])

query T
Expand Down
6 changes: 3 additions & 3 deletions pkg/sql/logictest/testdata/logic_test/cascade
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ SELECT * FROM b;
1 2 3 4 5 1006 7 8 9 10

# Also ensure that normal errors are still correctly wrapped even if cascading.
statement error pq: duplicate key value \(id\)=\(1\) violates unique constraint "primary"
statement error pq: duplicate key value violates unique constraint "primary"\nDETAIL: Key \(id\)=\(1\) already exists\.
UPDATE a SET id = 1 WHERE id = 1006;

# 7. ON DELETE SET NULL
Expand Down Expand Up @@ -3293,7 +3293,7 @@ statement oK
INSERT INTO a VALUES ('original'), ('default');
INSERT INTO b VALUES ('b1', 'original'), ('b2', 'default');

statement error pq: duplicate key value \(a_id\)=\('default'\) violates unique constraint "b_a_id_key"
statement error pq: duplicate key value violates unique constraint "b_a_id_key"\nDETAIL: Key \(a_id\)=\('default'\) already exists\.
DELETE FROM a WHERE id = 'original';

# Clean up after the test.
Expand Down Expand Up @@ -3676,7 +3676,7 @@ statement oK
INSERT INTO a VALUES ('original'), ('default');
INSERT INTO b VALUES ('b1', 'original'), ('b2', 'default');

statement error pq: duplicate key value \(a_id\)=\('default'\) violates unique constraint "b_a_id_key"
statement error pq: duplicate key value violates unique constraint "b_a_id_key"\nDETAIL: Key \(a_id\)=\('default'\) already exists\.
UPDATE a SET id = 'updated' WHERE id = 'original';

# Clean up after the test.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ CREATE TABLE p (
statement ok
INSERT INTO p VALUES ('a' COLLATE en_u_ks_level1)

statement error duplicate key value \(a\)=\('a' COLLATE en_u_ks_level1\) violates unique constraint "primary"
statement error duplicate key value violates unique constraint "primary"\nDETAIL: Key \(a\)=\('a' COLLATE en_u_ks_level1\) already exists\.
INSERT INTO p VALUES ('A' COLLATE en_u_ks_level1)

statement ok
Expand Down
2 changes: 1 addition & 1 deletion pkg/sql/logictest/testdata/logic_test/datetime
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ SELECT * FROM t WHERE a = '2015-08-25 04:45:45.53453+01:00'::timestamp
2015-08-25 04:45:45.53453 +0000 +0000 2015-08-25 00:00:00 +0000 +0000 02:45:02.234

# insert duplicate value with different time zone offset
statement error duplicate key value \(a\)=\('2015-08-30 03:34:45\.34567'\) violates unique constraint "primary"
statement error duplicate key value violates unique constraint "primary"\nDETAIL: Key \(a\)=\('2015-08-30 03:34:45\.34567'\) already exists\.
INSERT INTO t VALUES
('2015-08-30 03:34:45.34567-07:00', '2015-08-31', '35h2s')

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ vectorized: <hidden>
│ spans: LIMITED SCAN
│ limit: 1
└── • fk-check
└── • constraint-check
└── • error if rows
│ actual row count: 0
Expand Down
2 changes: 1 addition & 1 deletion pkg/sql/logictest/testdata/logic_test/fk
Original file line number Diff line number Diff line change
Expand Up @@ -2824,7 +2824,7 @@ INSERT INTO child (c, p) VALUES (200, 2)

# These two test cases are sort of undefined behavior, since their
# success/failure depends on the order in which the updates are performed.
statement error duplicate key value \(p\)=\(3\) violates unique constraint "primary"
statement error duplicate key value violates unique constraint "primary"\nDETAIL: Key \(p\)=\(3\) already exists\.
UPDATE parent SET p = p + 1

statement ok
Expand Down
2 changes: 1 addition & 1 deletion pkg/sql/logictest/testdata/logic_test/hash_sharded_index
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ sharded_primary CREATE TABLE public.sharded_primary (
statement ok
INSERT INTO sharded_primary values (1), (2), (3)

query error pq: duplicate key value \(crdb_internal_a_shard_10,a\)=\(6,1\) violates unique constraint "primary"
query error pq: duplicate key value violates unique constraint "primary"\nDETAIL: Key \(crdb_internal_a_shard_10,a\)=\(6,1\) already exists\.
INSERT INTO sharded_primary values (1)

# Ensure that the shard column is assigned into the column family of the first column in
Expand Down
8 changes: 4 additions & 4 deletions pkg/sql/logictest/testdata/logic_test/insert
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,13 @@ SELECT v || 'hello' FROM [INSERT INTO kv VALUES ('e', 'f'), ('g', '') RETURNING
fhello
hello

statement error pgcode 23505 duplicate key value \(v\)=\('f'\) violates unique constraint "a"
statement error pgcode 23505 duplicate key value violates unique constraint "a"\nDETAIL: Key \(v\)=\('f'\) already exists\.
INSERT INTO kv VALUES ('h', 'f')

statement ok
INSERT INTO kv VALUES ('f', 'g')

statement error duplicate key value \(v\)=\('g'\) violates unique constraint "a"
statement error duplicate key value violates unique constraint "a"\nDETAIL: Key \(v\)=\('g'\) already exists\.
INSERT INTO kv VALUES ('h', 'g')

query TT
Expand Down Expand Up @@ -330,7 +330,7 @@ INSERT INTO abc VALUES (1, 2, 10)

# Verify we get the correct message, even though internally the ConditionalPut
# for the index key will also fail.
statement error pgcode 23505 duplicate key value \(a,b\)=\(1,2\) violates unique constraint "primary"
statement error pgcode 23505 duplicate key value violates unique constraint "primary"\nDETAIL: Key \(a,b\)=\(1,2\) already exists\.
INSERT INTO abc VALUES (1, 2, 20)

statement ok
Expand All @@ -352,7 +352,7 @@ CREATE TABLE blindcput (

# The optimization thresholds at 10 k/v operations, so we need at least that
# many in one batch to trigger it.
statement error duplicate key value \(x\)=\(1\) violates unique constraint "primary"
statement error duplicate key value violates unique constraint "primary"\nDETAIL: Key \(x\)=\(1\) already exists\.
INSERT INTO blindcput values (1, 1), (2, 2), (3, 3), (4, 4), (1, 5)

statement ok
Expand Down
6 changes: 3 additions & 3 deletions pkg/sql/logictest/testdata/logic_test/interleaved
Original file line number Diff line number Diff line change
Expand Up @@ -369,17 +369,17 @@ INSERT INTO p20067 VALUES (1, 'John Doe');
INSERT INTO c20067 VALUES (1, 1, 'John Doe Junior');
COMMIT;

statement error duplicate key value \(name\)=\('John Doe Junior'\) violates unique constraint "uq_name"
statement error duplicate key value violates unique constraint "uq_name"\nDETAIL: Key \(name\)=\('John Doe Junior'\) already exists\.
INSERT INTO c20067 VALUES (2, 1, 'John Doe Junior')

statement error duplicate key value \(name\)=\('John Doe Junior'\) violates unique constraint "uq_name"
statement error duplicate key value violates unique constraint "uq_name"\nDETAIL: Key \(name\)=\('John Doe Junior'\) already exists\.
BEGIN; INSERT INTO p20067 VALUES (2, 'John Doe'); INSERT INTO c20067 VALUES (2, 1, 'John Doe Junior'); END;

# End the last transaction.
statement ok
END

statement error duplicate key value \(p_id,c_id\)=\(1,1\) violates unique constraint "primary"
statement error duplicate key value violates unique constraint "primary"\nDETAIL: Key \(p_id,c_id\)=\(1,1\) already exists\.
INSERT INTO c20067 VALUES (1, 1, 'John Doe')

# Regression test for #26756: ensure that interleaved table joins don't get
Expand Down
2 changes: 1 addition & 1 deletion pkg/sql/logictest/testdata/logic_test/materialized_view
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ CREATE MATERIALIZED VIEW v_dup AS SELECT x FROM dup;
CREATE UNIQUE INDEX i ON v_dup (x);
INSERT INTO dup VALUES (1), (1);

statement error pq: duplicate key value \(x\)=\(1\) violates unique constraint "i"
statement error pq: duplicate key value violates unique constraint "i"\nDETAIL: Key \(x\)=\(1\) already exists\.
REFRESH MATERIALIZED VIEW v_dup

# We shouldn't be able to mix materialized and non materialized views in DDLs.
Expand Down
4 changes: 2 additions & 2 deletions pkg/sql/logictest/testdata/logic_test/multi_statement
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ c d

# error if either statement returns an error
# first statement returns an error. Second stmt shouldn't execute.
statement error duplicate key value \(k\)=\('a'\) violates unique constraint "primary"
statement error duplicate key value violates unique constraint "primary"\nDETAIL: Key \(k\)=\('a'\) already exists\.
INSERT INTO kv (k,v) VALUES ('a', 'b'); INSERT INTO kv (k,v) VALUES ('e', 'f')

query TT rowsort
Expand All @@ -29,7 +29,7 @@ a b
c d

# second statement returns an error
statement error duplicate key value \(k\)=\('a'\) violates unique constraint "primary"
statement error duplicate key value violates unique constraint "primary"\nDETAIL: Key \(k\)=\('a'\) already exists\.
INSERT INTO kv (k,v) VALUES ('g', 'h'); INSERT INTO kv (k,v) VALUES ('a', 'b')

query TT rowsort
Expand Down
12 changes: 6 additions & 6 deletions pkg/sql/logictest/testdata/logic_test/parallel_stmts_compat
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ CREATE TABLE fk(
statement ok
INSERT INTO kv VALUES (1, 2) RETURNING NOTHING

statement error duplicate key value \(k\)=\(1\) violates unique constraint "primary"
statement error duplicate key value violates unique constraint "primary"\nDETAIL: Key \(k\)=\(1\) already exists\.
INSERT INTO kv VALUES (1, 2) RETURNING NOTHING

statement ok
Expand All @@ -33,7 +33,7 @@ UPSERT INTO kv VALUES (2, 500) RETURNING NOTHING
statement ok
UPDATE kv SET v = k WHERE k = 3 RETURNING NOTHING

statement error duplicate key value \(k\)=\(1\) violates unique constraint "primary"
statement error duplicate key value violates unique constraint "primary"\nDETAIL: Key \(k\)=\(1\) already exists\.
UPDATE kv SET k = 1 WHERE k = 2 RETURNING NOTHING

statement ok
Expand Down Expand Up @@ -84,7 +84,7 @@ BEGIN
statement ok
INSERT INTO kv VALUES (4, 5) RETURNING NOTHING

statement error duplicate key value \(k\)=\(2\) violates unique constraint "primary"
statement error duplicate key value violates unique constraint "primary"\nDETAIL: Key \(k\)=\(2\) already exists\.
INSERT INTO kv VALUES (2, 3) RETURNING NOTHING

statement error current transaction is aborted, commands ignored until end of transaction block
Expand Down Expand Up @@ -190,7 +190,7 @@ BEGIN
statement ok
UPDATE kv SET k = 9 WHERE k = 1 RETURNING NOTHING

statement error duplicate key value \(k\)=\(3\) violates unique constraint "primary"
statement error duplicate key value violates unique constraint "primary"\nDETAIL: Key \(k\)=\(3\) already exists\.
UPDATE kv SET k = 3 WHERE k = 2 RETURNING NOTHING

statement error current transaction is aborted, commands ignored until end of transaction block
Expand Down Expand Up @@ -316,7 +316,7 @@ SELECT k, v FROM kv ORDER BY k
statement ok
BEGIN

statement error duplicate key value \(k\)=\(1\) violates unique constraint "primary"
statement error duplicate key value violates unique constraint "primary"\nDETAIL: Key \(k\)=\(1\) already exists\.
INSERT INTO kv VALUES (1, 2) RETURNING NOTHING

statement error current transaction is aborted, commands ignored until end of transaction block
Expand Down Expand Up @@ -361,7 +361,7 @@ BEGIN
statement ok
EXECUTE x(1, 2)

statement error duplicate key value \(k\)=\(1\) violates unique constraint "primary"
statement error duplicate key value violates unique constraint "primary"\nDETAIL: Key \(k\)=\(1\) already exists\.
EXECUTE x(1, 2)

statement ok
Expand Down
12 changes: 6 additions & 6 deletions pkg/sql/logictest/testdata/logic_test/partial_index
Original file line number Diff line number Diff line change
Expand Up @@ -660,15 +660,15 @@ CREATE TABLE u (
)

# Inserting multiple rows that conflicts fails.
statement error pgcode 23505 duplicate key value \(a\)=\(1\) violates unique constraint \"i\"
statement error pgcode 23505 duplicate key value violates unique constraint \"i\"\nDETAIL: Key \(a\)=\(1\) already exists\.
INSERT INTO u VALUES (1, 1), (1, 2)

# Inserting multiple rows that don't conflict succeeds.
statement ok
INSERT INTO u VALUES (1, 1), (2, 2), (1, -1)

# Inserting a row that conflicts with an existing row fails.
statement error pgcode 23505 duplicate key value \(a\)=\(1\) violates unique constraint \"i\"
statement error pgcode 23505 duplicate key value violates unique constraint \"i\"\nDETAIL: Key \(a\)=\(1\) already exists\.
INSERT INTO u VALUES (1, 3)

query II rowsort
Expand All @@ -684,12 +684,12 @@ DELETE FROM u WHERE a = 2;
INSERT INTO u VALUES (2, 2);

# Updating a row in the unique partial index to conflict with another row fails.
statement error pgcode 23505 duplicate key value \(a\)=\(2\) violates unique constraint \"i\"
statement error pgcode 23505 duplicate key value violates unique constraint \"i\"\nDETAIL: Key \(a\)=\(2\) already exists\.
UPDATE u SET a = 2 WHERE b = 1

# Updating a row not in the unique partial index to conflict with a row in the
# index fails.
statement error pgcode 23505 duplicate key value \(a\)=\(2\) violates unique constraint \"i\"
statement error pgcode 23505 duplicate key value violates unique constraint \"i\"\nDETAIL: Key \(a\)=\(2\) already exists\.
UPDATE u SET a = 2, b = 1 WHERE b = -1

# Updating a row not in the unique index to remain out of the unique index
Expand Down Expand Up @@ -885,7 +885,7 @@ statement ok
CREATE UNIQUE INDEX i2 ON u (a) WHERE b < 0;
INSERT INTO u VALUES (-1, -1);

statement error pgcode 23505 duplicate key value \(a\)=\(-1\) violates unique constraint \"i2\"
statement error pgcode 23505 duplicate key value violates unique constraint \"i2\"\nDETAIL: Key \(a\)=\(-1\) already exists\.
INSERT INTO u VALUES (-1, -1) ON CONFLICT (a) WHERE b > 0 DO NOTHING

# Two arbiters can be used to detect conflicts and avoid duplicate key errors.
Expand Down Expand Up @@ -1005,7 +1005,7 @@ CREATE UNIQUE INDEX i2 ON u (a) WHERE b < 0;

# There can be duplicate key errors from unique partial indexes that are not
# arbiters.
statement error pgcode 23505 duplicate key value \(a\)=\(1\) violates unique constraint \"i2\"
statement error pgcode 23505 duplicate key value violates unique constraint \"i2\"\nDETAIL: Key \(a\)=\(1\) already exists\.
INSERT INTO u VALUES (1, -1) ON CONFLICT (a) WHERE b > 0 DO UPDATE SET a = 100

statement ok
Expand Down
2 changes: 1 addition & 1 deletion pkg/sql/logictest/testdata/logic_test/txn
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ a c
statement ok
BEGIN

statement error duplicate key value \(k\)=\('a'\) violates unique constraint "primary"
statement error duplicate key value violates unique constraint "primary"\nDETAIL: Key \(k\)=\('a'\) already exists\.
INSERT INTO kv VALUES('unique_key', 'some value');
INSERT INTO kv VALUES('a', 'c');
INSERT INTO kv VALUES('unique_key2', 'some value');
Expand Down
Loading

0 comments on commit 862edb7

Please sign in to comment.