# LogicTest: !weak-iso-level-configs
# READ COMMITTED and REPEATABLE READ do not work with UNIQUE WITHOUT INDEX
# constraints. See https://github.com/cockroachdb/cockroach/issues/110873.

statement ok
SET experimental_enable_unique_without_index_constraints = true

statement ok
CREATE TABLE uniq (
  k INT PRIMARY KEY,
  v INT UNIQUE,
  w INT UNIQUE WITHOUT INDEX,
  x INT,
  y INT DEFAULT 5,
  UNIQUE WITHOUT INDEX (x, y)
)

statement ok
CREATE TABLE uniq_overlaps_pk (
  a INT,
  b INT,
  c INT,
  d INT,
  PRIMARY KEY (a, b),
  UNIQUE WITHOUT INDEX (b, c),
  UNIQUE WITHOUT INDEX (a, b, d),
  UNIQUE WITHOUT INDEX (a),
  UNIQUE WITHOUT INDEX (c, d)
)

statement ok
CREATE TABLE uniq_hidden_pk (
  a INT,
  b INT,
  c INT,
  d INT,
  UNIQUE WITHOUT INDEX (b, c),
  UNIQUE WITHOUT INDEX (a, b, d),
  UNIQUE WITHOUT INDEX (a)
)

statement ok
CREATE TABLE uniq_fk_parent (
  a INT UNIQUE,
  b INT,
  c INT,
  d INT UNIQUE WITHOUT INDEX,
  e INT UNIQUE WITHOUT INDEX,
  UNIQUE WITHOUT INDEX (b, c)
)

statement ok
CREATE TABLE uniq_fk_child (
  a INT,
  b INT,
  c INT,
  d INT REFERENCES uniq_fk_parent (d),
  e INT REFERENCES uniq_fk_parent (e) ON DELETE SET NULL,
  FOREIGN KEY (b, c) REFERENCES uniq_fk_parent (b, c) ON UPDATE CASCADE,
  UNIQUE WITHOUT INDEX (c)
)

statement error column "b" does not exist
CREATE TABLE uniq_partial (
  a INT,
  UNIQUE WITHOUT INDEX (a) WHERE b > 0
)

statement ok
CREATE TABLE uniq_partial (
  a INT,
  b INT,
  UNIQUE WITHOUT INDEX (a) WHERE b > 0
)

statement ok
CREATE TABLE uniq_partial_pk (
  k INT PRIMARY KEY,
  a INT,
  b INT,
  UNIQUE WITHOUT INDEX (a) WHERE b > 0
)

statement ok
CREATE TYPE region AS ENUM ('us-east', 'us-west', 'eu-west')

# TODO(rytaft): When more of the multi-region syntax is supported,
# add it here.
statement ok
CREATE TABLE uniq_enum (
  r region DEFAULT 'us-east',
  s STRING,
  i INT,
  j INT DEFAULT NULL,
  PRIMARY KEY (r, i),
  UNIQUE INDEX (r, s, j),
  UNIQUE WITHOUT INDEX (i),
  UNIQUE WITHOUT INDEX (s, j)
)

statement ok
CREATE TABLE uniq_computed_pk (
  i INT,
  s STRING,
  d DECIMAL,
  c_i_expr STRING AS (CASE WHEN i < 0 THEN 'foo' ELSE 'bar' END) STORED,
  c_s STRING AS (s) VIRTUAL,
  c_d DECIMAL AS (d) STORED,
  c_d_expr STRING AS (d::string) STORED,
  PRIMARY KEY (c_i_expr, i),
  UNIQUE (c_s, s),
  UNIQUE (c_d_expr, d),
  UNIQUE WITHOUT INDEX (i),
  UNIQUE WITHOUT INDEX (s),
  UNIQUE WITHOUT INDEX (d)
)

statement ok
CREATE TABLE uniq_uuid (
  id1 UUID,
  id2 UUID,
  UNIQUE WITHOUT INDEX (id1),
  UNIQUE WITHOUT INDEX (id2)
)

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

# Insert some data into the other table.
statement ok
INSERT INTO other VALUES (10, 10, 1, 1, 1, '8597b0eb-7b89-4857-858a-fabf86f6a3ac')


# -- Tests with INSERT --
subtest Insert

# Insert some non-null data.
statement ok
INSERT INTO uniq VALUES (1, 1, 1, 1, 1), (2, 2, 2, 2, 2)

# Regular primary key violation.
statement error pgcode 23505 pq: duplicate key value violates unique constraint "uniq_pkey"\nDETAIL: Key \(k\)=\(1\) already exists\.
INSERT INTO uniq VALUES (1, 1, 1, 1, 1)

# Regular unique index violation.
statement error pgcode 23505 pq: duplicate key value violates unique constraint "uniq_v_key"\nDETAIL: Key \(v\)=\(1\) already exists\.
INSERT INTO uniq VALUES (3, 1, 1, 1, 1)

# Attempt to insert the same keys twice in the same statement.
statement error pgcode 23505 pq: duplicate key value violates unique constraint "unique_w"\nDETAIL: Key \(w\)=\(3\) already exists\.
INSERT INTO uniq VALUES (3, 3, 3, 3, 3), (4, 4, 3, 3, 3)

statement error pgcode 23505 pq: duplicate key value violates unique constraint "unique_w"\nDETAIL: Key \(w\)=\(1\) already exists\.
INSERT INTO uniq VALUES (3, 3, 1, 1, 1)

statement error pgcode 23505 pq: duplicate key value violates unique constraint "unique_x_y"\nDETAIL: Key \(x, y\)=\(1, 1\) already exists\.
INSERT INTO uniq VALUES (3, 3, 3, 1, 1)

# Even though y=1 already exists, (x,y)=(3,1) is unique.
statement ok
INSERT INTO uniq VALUES (3, 3, 3, 3, 1)

# Inserting these rows should succeed since at least one of the columns in each
# UNIQUE WITHOUT INDEX constraint is null.
statement ok
INSERT INTO uniq VALUES (4, 4, NULL, NULL, 1), (5, 5, NULL, 2, NULL), (6, 6, NULL, NULL, 1), (7, 7, NULL, 2, NULL)

# Insert with non-constant input.
statement error pgcode 23505 pq: duplicate key value violates unique constraint "unique_w"\nDETAIL: Key \(w\)=\(1\) already exists\.
INSERT INTO uniq SELECT k, v, w, x, y FROM other

# On conflict do nothing with constant input, conflict on UNIQUE WITHOUT INDEX
# column. The only row that is successfully inserted here is (400, 40, 4).
statement ok
INSERT INTO uniq VALUES (100, 10, 1), (200, 20, 2), (400, 40, 4) ON CONFLICT (w) DO NOTHING

# On conflict do nothing with constant input, conflict on UNIQUE WITHOUT INDEX
# column, conflicting insert rows.
# Only row (500, 50, 50) is inserted.
statement ok
INSERT INTO uniq VALUES (500, 50, 50), (600, 50, 50) ON CONFLICT (w) DO NOTHING

# On conflict do nothing with constant input, no conflict columns.
# The only row that is successfully inserted here is (20, 20, 20, 20, 20).
statement ok
INSERT INTO uniq VALUES (1, 20, 20, 20, 20), (20, 1, 20, 20, 20), (20, 20, 20, 20, 20),
                        (20, 20, 1, 20, 20), (20, 20, 20, 1, 1) ON CONFLICT DO NOTHING

query IIIII colnames,rowsort
SELECT * FROM uniq
----
k    v   w     x     y
1    1   1     1     1
2    2   2     2     2
3    3   3     3     1
4    4   NULL  NULL  1
5    5   NULL  2     NULL
6    6   NULL  NULL  1
7    7   NULL  2     NULL
20   20  20    20    20
400  40  4     NULL  5
500  50  50    NULL  5


# Insert into a table in which the primary key overlaps some of the unique
# constraints.
statement ok
INSERT INTO uniq_overlaps_pk VALUES (1, 1, 1, 1), (2, 2, 2, 2)

statement error pgcode 23505 pq: duplicate key value violates unique constraint "unique_a"\nDETAIL: Key \(a\)=\(1\) already exists\.
INSERT INTO uniq_overlaps_pk VALUES (1, 2, 3, 4)

statement error pgcode 23505 pq: duplicate key value violates unique constraint "unique_b_c"\nDETAIL: Key \(b, c\)=\(1, 1\) already exists\.
INSERT INTO uniq_overlaps_pk VALUES (3, 1, 1, 3)

statement error pgcode 23505 pq: duplicate key value violates unique constraint "unique_c_d"\nDETAIL: Key \(c, d\)=\(1, 1\) already exists\.
INSERT INTO uniq_overlaps_pk VALUES (3, 3, 1, 1)

statement ok
INSERT INTO uniq_overlaps_pk VALUES (3, 3, 1, 3)

query IIII colnames,rowsort
SELECT * FROM uniq_overlaps_pk
----
a  b  c  d
1  1  1  1
2  2  2  2
3  3  1  3


# Insert into a table with a hidden primary key.
statement ok
INSERT INTO uniq_hidden_pk VALUES (1, 1, 1, 1), (2, 2, 2, 2)

# Insert with non-constant input.
statement error pgcode 23505 pq: duplicate key value violates unique constraint "unique_b_c"\nDETAIL: Key \(b, c\)=\(1, 1\) already exists\.
INSERT INTO uniq_hidden_pk SELECT k, w, x, y FROM other

query IIII colnames,rowsort
SELECT * FROM uniq_hidden_pk
----
a  b  c  d
1  1  1  1
2  2  2  2


# Combine unique checks with foreign keys.
statement ok
INSERT INTO uniq_fk_parent VALUES (1, 1, 1, 1, 1), (2, 2, 2, 2, 2);
INSERT INTO uniq_fk_child VALUES (1, 1, 1, 1, 1), (2, 2, 2, 2, 2)

# This passes the foreign key checks but fails the uniqueness checks.
statement error pgcode 23505 pq: duplicate key value violates unique constraint "unique_c"\nDETAIL: Key \(c\)=\(1\) already exists\.
INSERT INTO uniq_fk_child VALUES (1, 1, 1), (2, 2, 2)

# This fails the foreign key checks but passes the uniqueness checks.
statement error pgcode 23503 pq: insert on table "uniq_fk_child" violates foreign key constraint "uniq_fk_child_b_c_fkey"\nDETAIL: Key \(b, c\)=\(., .\) is not present in table "uniq_fk_parent"\.
INSERT INTO uniq_fk_child VALUES (3, 3, 3), (4, 4, 4)

# This fails both types of checks.
statement error pgcode 23505 pq: duplicate key value violates unique constraint "unique_c"\nDETAIL: Key \(c\)=\(2\) already exists\.
INSERT INTO uniq_fk_child VALUES (1, 1, 2), (4, 2, 2)

query IIIII colnames,rowsort
SELECT * FROM uniq_fk_child
----
a  b  c  d  e
1  1  1  1  1
2  2  2  2  2


# Insert into a table in which the unique constraints are the suffix of an
# index, and the prefix of the index is an enum.
statement ok
INSERT INTO uniq_enum VALUES ('us-west', 'foo', 1, 1), ('eu-west', 'bar', 2, 2)

# Insert into a table in which the unique constraints are the suffix of an
# index, and the prefix of the index is an enum. This case uses the default
# value for columns r and j.
statement error pgcode 23505 pq: duplicate key value violates unique constraint "unique_i"\nDETAIL: Key \(i\)=\(1\) already exists\.
INSERT INTO uniq_enum (s, i) VALUES ('foo', 1), ('bar', 3)

query TTII colnames,rowsort
SELECT * FROM uniq_enum
----
r        s    i  j
us-west  foo  1  1
eu-west  bar  2  2


# Insert some non-null data into a table with a partial unique without index
# constraint.
statement ok
INSERT INTO uniq_partial VALUES (1, 1), (1, -1), (2, 2)

# Partial unique constraint violation.
statement error pgcode 23505 pq: duplicate key value violates unique constraint "unique_a"\nDETAIL: Key \(a\)=\(1\) already exists\.
INSERT INTO uniq_partial VALUES (1, 3)

# No partial unique constraint violation because b <= 0.
statement ok
INSERT INTO uniq_partial VALUES (1, -3)

# Attempt to insert conflicting keys twice in the same statement.
statement error pgcode 23505 pq: duplicate key value violates unique constraint "unique_a"\nDETAIL: Key \(a\)=\(3\) already exists\.
INSERT INTO uniq_partial VALUES (3, 3), (3, 4)

# Attempt to insert one conflicting key and one non-conflicting key in the same
# statement.
statement error pgcode 23505 pq: duplicate key value violates unique constraint "unique_a"\nDETAIL: Key \(a\)=\(1\) already exists\.
INSERT INTO uniq_partial VALUES (1, 3), (3, 3)

# Insert some rows with NULL keys.
statement ok
INSERT INTO uniq_partial VALUES (NULL, 5), (5, 5), (NULL, 5)

# Insert with non-constant input.
statement error pgcode 23505 pq: duplicate key value violates unique constraint "unique_a"\nDETAIL: Key \(a\)=\(1\) already exists\.
INSERT INTO uniq_partial SELECT w, x FROM other

statement error there is no unique or exclusion constraint matching the ON CONFLICT specification
INSERT INTO uniq_partial VALUES (1, 6), (6, 6) ON CONFLICT (a) DO NOTHING

# On conflict do nothing with constant input, conflict on UNIQUE WITHOUT INDEX
# column. Only the non-conflicting row (6, 6) is inserted.
statement ok
INSERT INTO uniq_partial VALUES (1, 6), (6, 6) ON CONFLICT (a) WHERE b > 0 DO NOTHING

# On conflict do nothing with constant input, conflict on UNIQUE WITHOUT INDEX
# column, conflicting insert rows.
# Only rows (7, 7) and (7, -7) are inserted.
statement ok
INSERT INTO uniq_partial VALUES (7, 7), (7, 8), (7, -7) ON CONFLICT (a) WHERE b > 0 DO NOTHING

# On conflict do nothing with constant input, no conflict columns.
# Only one row (9, 9) and (9, -9) are inserted.
statement ok
INSERT INTO uniq_partial VALUES (1, 9), (9, 9), (9, 9), (9, -9) ON CONFLICT DO NOTHING

# On conflict do nothing with non-constant input.
# The (1, 10) row is not inserted because of a conflict with (1, 1).
statement ok
INSERT INTO uniq_partial SELECT w, k FROM other ON CONFLICT DO NOTHING

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

# Check that uniqueness violations are detected in a table with UNIQUE indexes
# containing computed columns that are dependent on UNIQUE WITHOUT INDEX
# columns.
statement ok
INSERT INTO uniq_computed_pk (i, s, d) VALUES (1, 'a', 1.0), (2, 'b', 2.0)

statement error pgcode 23505 pq: duplicate key value violates unique constraint "uniq_computed_pk_pkey"\nDETAIL: Key \(c_i_expr, i\)=\('bar', 1\) already exists\.
INSERT INTO uniq_computed_pk (i, s, d) VALUES (1, 'c', 3.0)

statement error pgcode 23505 pq: duplicate key value violates unique constraint "uniq_computed_pk_c_s_s_key"\nDETAIL: Key \(c_s, s\)=\('b', 'b'\) already exists\.
INSERT INTO uniq_computed_pk (i, s, d) VALUES (3, 'b', 3.0)

statement error pgcode 23505 pq: duplicate key value violates unique constraint "unique_d"\nDETAIL: Key \(d\)=\(1\.00\) already exists\.
INSERT INTO uniq_computed_pk (i, s, d) VALUES (3, 'c', 1.00)

query ITFTTFT colnames,rowsort
SELECT * FROM uniq_computed_pk
----
i  s  d    c_i_expr  c_s  c_d  c_d_expr
1  a  1.0  bar       a    1.0  1.0
2  b  2.0  bar       b    2.0  2.0

# Insert a couple of rows into a table with UUID columns.
statement ok
INSERT INTO uniq_uuid (id1, id2) SELECT gen_random_uuid(), '8597b0eb-7b89-4857-858a-fabf86f6a3ac'

# We can catch uniqueness violations on UUID columns set to a value other than
# gen_random_uuid().
statement error pgcode 23505 pq: duplicate key value violates unique constraint "unique_id2"\nDETAIL: Key \(id2\)=\('8597b0eb-7b89-4857-858a-fabf86f6a3ac'\) already exists\.
INSERT INTO uniq_uuid (id1, id2) SELECT gen_random_uuid(), u FROM other


# -- Tests with UPDATE --
subtest Update

# Set w to the same value it already has.
statement ok
UPDATE uniq SET w = 1, x = 2 WHERE k = 1

statement error pgcode 23505 pq: duplicate key value violates unique constraint "unique_w"\nDETAIL: Key \(w\)=\(1\) already exists\.
UPDATE uniq SET w = 1, x = 2 WHERE k = 2

# Fails because we are trying to update every row with the same values.
statement error pgcode 23505 pq: duplicate key value violates unique constraint "unique_w"\nDETAIL: Key \(w\)=\(100\) already exists\.
UPDATE uniq SET w = 100, x = 200

# This update targets the row (2, 2, 2, 2, 2).
statement ok
UPDATE uniq SET k = 10, v = 10, w = 10, x = NULL WHERE k = 2

# This insert should succeed now.
statement ok
INSERT INTO uniq VALUES (2, 2, 2, 2, 2)

# No UNIQUE WITHOUT INDEX checks since none of the columns requiring checks are
# updated.
statement ok
UPDATE uniq SET k = 11, v = 11 WHERE k = 10

query IIIII colnames,rowsort
SELECT * FROM uniq
----
k    v   w     x     y
1    1   1     2     1
2    2   2     2     2
3    3   3     3     1
4    4   NULL  NULL  1
5    5   NULL  2     NULL
6    6   NULL  NULL  1
7    7   NULL  2     NULL
11   11  10    NULL  2
20   20  20    20    20
400  40  4     NULL  5
500  50  50    NULL  5


# Update a table with multiple primary key columns.
# There are no rows with a=5.
statement ok
UPDATE uniq_overlaps_pk SET a = 1, b = 2, c = 3, d = 4 WHERE a = 5

statement error pgcode 23505 pq: duplicate key value violates unique constraint "unique_a"\nDETAIL: Key \(a\)=\(1\) already exists\.
UPDATE uniq_overlaps_pk SET a = 1, b = 2, c = 3, d = 4 WHERE a = 3

query IIII colnames,rowsort
SELECT * FROM uniq_overlaps_pk
----
a  b  c  d
1  1  1  1
2  2  2  2
3  3  1  3


# Try to update a table with a hidden primary key with non-constant input.
statement error pgcode 23505 pq: duplicate key value violates unique constraint "unique_a"\nDETAIL: Key \(a\)=\(10\) already exists\.
UPDATE uniq_hidden_pk SET a = k FROM other

query IIII colnames,rowsort
SELECT * FROM uniq_hidden_pk
----
a  b  c  d
1  1  1  1
2  2  2  2


# Combine unique checks with foreign keys.
# The cascade here should cause a uniqueness error for the child.
statement error pgcode 23505 pq: duplicate key value violates unique constraint "unique_c"\nDETAIL: Key \(c\)=\(1\) already exists\.
UPDATE uniq_fk_parent SET c = 1

# Inbound foreign key check should fail.
statement error pgcode 23503 pq: update on table "uniq_fk_parent" violates foreign key constraint "uniq_fk_child_d_fkey" on table "uniq_fk_child"\nDETAIL: Key \(d\)=\(2\) is still referenced from table "uniq_fk_child"\.
UPDATE uniq_fk_parent SET d = 3 WHERE a = 2

# Combine unique checks with foreign keys.
# This passes the foreign key checks but fails the uniqueness check.
statement error pgcode 23505 pq: duplicate key value violates unique constraint "unique_c"\nDETAIL: Key \(c\)=\(2\) already exists\.
UPDATE uniq_fk_child SET b = 2, c = 2

query IIIII colnames,rowsort
SELECT * FROM uniq_fk_child
----
a  b  c  d  e
1  1  1  1  1
2  2  2  2  2


# Update a table in which the unique constraints are the suffix of an
# index, and the prefix of the index is an enum.
statement error pgcode 23505 pq: duplicate key value violates unique constraint "unique_s_j"\nDETAIL: Key \(s, j\)=\('foo', 1\) already exists\.
UPDATE uniq_enum SET r = DEFAULT, s = 'foo', j = 1 WHERE r = 'eu-west'

query TTII colnames,rowsort
SELECT * FROM uniq_enum
----
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

# Set a to a value that would conflict if it was a non-partial unique constraint.
statement ok
UPDATE uniq_partial SET a = 1 WHERE b = -7

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

# Check that uniqueness violations are detected in a table with UNIQUE indexes
# containing computed columns that are dependent on UNIQUE WITHOUT INDEX
# columns.
statement error pgcode 23505 pq: duplicate key value violates unique constraint "uniq_computed_pk_pkey"\nDETAIL: Key \(c_i_expr, i\)=\('bar', 1\) already exists\.
UPDATE uniq_computed_pk SET i = 1 WHERE i = 2

statement error pgcode 23505 pq: duplicate key value violates unique constraint "uniq_computed_pk_c_s_s_key"\nDETAIL: Key \(c_s, s\)=\('a', 'a'\) already exists\.
UPDATE uniq_computed_pk SET s = 'a' WHERE i = 2

statement error pgcode 23505 pq: duplicate key value violates unique constraint "unique_d"\nDETAIL: Key \(d\)=\(1\.00\) already exists\.
UPDATE uniq_computed_pk SET d = 1.00 WHERE i = 2

query ITFTTFT colnames,rowsort
SELECT * FROM uniq_computed_pk
----
i  s  d    c_i_expr  c_s  c_d  c_d_expr
1  a  1.0  bar       a    1.0  1.0
2  b  2.0  bar       b    2.0  2.0


# -- Tests with UPSERT --
subtest Upsert

# Upsert some non-null data.
statement ok
UPSERT INTO uniq VALUES (1, 1, 1, 1, 1), (3, 3, 3, 3, 3), (5, 5, 5, 5, 5), (8, 8, 8, 8, 8)

# Attempt to upsert the same keys twice in the same statement.
statement error pgcode 23505 pq: duplicate key value violates unique constraint "unique_w"\nDETAIL: Key \(w\)=\(3\) already exists\.
UPSERT INTO uniq VALUES (3, 3, 3, 3, 3), (4, 4, 3, 3, 3)

# Duplicate error on update path.
statement error pgcode 23505 pq: duplicate key value violates unique constraint "unique_w"\nDETAIL: Key \(w\)=\(1\) already exists\.
UPSERT INTO uniq VALUES (3, 3, 1, 1, 1)

# Duplicate error on insert path.
statement error pgcode 23505 pq: duplicate key value violates unique constraint "unique_x_y"\nDETAIL: Key \(x, y\)=\(1, 1\) already exists\.
UPSERT INTO uniq VALUES (9, 9, 9, 1, 1)

# Even though y=2 already exists, (x,y)=(3,2) is unique.
statement ok
UPSERT INTO uniq VALUES (3, 3, 3, 3, 2)

# Upserting these rows should succeed since at least one of the columns in each
# UNIQUE WITHOUT INDEX constraint is null.
statement ok
UPSERT INTO uniq VALUES (8, 8, NULL, NULL, 1), (9, 9, NULL, 1, NULL)

# Upsert using default value for y.
statement error pgcode 23505 pq: duplicate key value violates unique constraint "unique_x_y"\nDETAIL: Key \(x, y\)=\(5, 5\) already exists\.
UPSERT INTO uniq (k, v, w, x) VALUES (5, 5, NULL, 5), (10, 10, NULL, 5)

# Upsert using default values for w, x and y.
statement ok
UPSERT INTO uniq (k, v) VALUES (5, 5), (10, 10)

# On conflict do update with constant input.
# This sets w to NULL where v = 1 since the default value of w (which gets
# stored in excluded) is NULL.
statement ok
INSERT INTO uniq VALUES (1), (2) ON CONFLICT (k) DO UPDATE SET w = excluded.w + 1 WHERE uniq.v = 1

# On conflict do update with non-constant input.
# This sets w to 11 where v is 10.
statement ok
INSERT INTO uniq SELECT k, v FROM other ON CONFLICT (v) DO UPDATE SET w = uniq.k + 1

# On conflict do update with non-constant input.
statement error pgcode 23505 pq: duplicate key value violates unique constraint "unique_w"\nDETAIL: Key \(w\)=\(5\) already exists\.
INSERT INTO uniq SELECT k, v FROM other ON CONFLICT (v) DO UPDATE SET w = 5

# On conflict do update with non-constant input.
statement error pgcode 23505 pq: duplicate key value violates unique constraint "unique_x_y"\nDETAIL: Key \(x, y\)=\(5, 5\) already exists\.
INSERT INTO uniq SELECT k, v FROM other ON CONFLICT (v) DO UPDATE SET x = 5

# On conflict do update with constant input, conflict on UNIQUE WITHOUT INDEX
# column.
statement error pgcode 23505 pq: duplicate key value violates unique constraint "unique_w"\nDETAIL: Key \(w\)=\(10\) already exists\.
INSERT INTO uniq VALUES (100, 100, 1), (200, 200, 2) ON CONFLICT (w) DO UPDATE SET w = 10

# On conflict do update with constant input, conflict on UNIQUE WITHOUT INDEX
# column.
statement ok
INSERT INTO uniq VALUES (100, 100, 1), (200, 200, 2) ON CONFLICT (w) DO UPDATE SET w = 12

# On conflict do update with constant input, conflict on UNIQUE WITHOUT INDEX
# columns.
statement ok
INSERT INTO uniq (k, v, x, y) VALUES (200, 200, 5, 5) ON CONFLICT (x, y) DO UPDATE SET w = 13, y = excluded.y + 1

query IIIII colnames,rowsort
SELECT * FROM uniq
----
k    v    w     x     y
1    1    NULL  1     1
2    2    12    2     2
3    3    3     3     2
4    4    NULL  NULL  1
5    5    13    5     6
6    6    NULL  NULL  1
7    7    NULL  2     NULL
8    8    NULL  NULL  1
9    9    NULL  1     NULL
10   10   11    NULL  5
11   11   10    NULL  2
20   20   20    20    20
100  100  1     NULL  5
400  40   4     NULL  5
500  50   50    NULL  5


# Upsert into a table in which the primary key overlaps some of the unique
# constraints.

statement ok
UPSERT INTO uniq_overlaps_pk VALUES (1, 1, 1, 1), (2, 2, 2, 2)

statement error pgcode 23505 pq: duplicate key value violates unique constraint "unique_a"\nDETAIL: Key \(a\)=\(1\) already exists\.
UPSERT INTO uniq_overlaps_pk VALUES (1, 2, 3, 4)

statement error pgcode 23505 pq: duplicate key value violates unique constraint "unique_b_c"\nDETAIL: Key \(b, c\)=\(1, 1\) already exists\.
UPSERT INTO uniq_overlaps_pk VALUES (3, 1, 1, 3)

statement error pgcode 23505 pq: duplicate key value violates unique constraint "unique_c_d"\nDETAIL: Key \(c, d\)=\(1, 1\) already exists\.
UPSERT INTO uniq_overlaps_pk VALUES (3, 3, 1, 1)

statement ok
UPSERT INTO uniq_overlaps_pk VALUES (3, 3, 1, 4)

# Inserts (10, 10, NULL, 1).
statement ok
UPSERT INTO uniq_overlaps_pk (a, b, d) SELECT k, v, x FROM other

# When the columns aren't specified, the default values for missing columns are
# used for both insert and update. This updates the last row to (10, 10, 1, NULL).
statement ok
UPSERT INTO uniq_overlaps_pk SELECT k, v, x FROM other

# When the columns are specified, the default values for missing columns are
# used for insert only. Updating to (10, 10, 1, 1) triggers a uniqueness error.
statement error pgcode 23505 pq: duplicate key value violates unique constraint "unique_c_d"\nDETAIL: Key \(c, d\)=\(1, 1\) already exists\.
UPSERT INTO uniq_overlaps_pk (a, b, d) SELECT k, v, x FROM other

query IIII colnames,rowsort
SELECT * FROM uniq_overlaps_pk
----
a   b   c  d
1   1   1  1
2   2   2  2
3   3   1  4
10  10  1  NULL


# Upsert with non-constant input, into a table with a hidden primary key.
statement error pgcode 23505 pq: duplicate key value violates unique constraint "unique_b_c"\nDETAIL: Key \(b, c\)=\(1, 1\) already exists\.
UPSERT INTO uniq_hidden_pk SELECT k, w, x, y FROM other

query IIII colnames,rowsort
SELECT * FROM uniq_hidden_pk
----
a  b  c  d
1  1  1  1
2  2  2  2


# Combine unique checks with foreign keys.
# The cascade here affects the unique column in uniq_fk_child.
statement error pgcode 23505 pq: duplicate key value violates unique constraint "unique_c"\nDETAIL: Key \(c\)=\(1\) already exists\.
INSERT INTO uniq_fk_parent VALUES (2, 1) ON CONFLICT (a) DO UPDATE SET c = 1

# Combine unique checks with foreign keys.
statement error pgcode 23505 pq: duplicate key value violates unique constraint "unique_c"\nDETAIL: Key \(c\)=\(1\) already exists\.
UPSERT INTO uniq_fk_child VALUES (2, 1, 1)

query IIIII colnames,rowsort
SELECT * FROM uniq_fk_child
----
a  b  c  d  e
1  1  1  1  1
2  2  2  2  2


# Upsert into a table in which the unique constraints are the suffix of an
# index, and the prefix of the index is an enum. This case uses the default
# value for columns r and j.
statement error pgcode 23505 pq: duplicate key value violates unique constraint "unique_i"\nDETAIL: Key \(i\)=\(2\) already exists\.
UPSERT INTO uniq_enum VALUES ('us-west', 'foo', 1, 1), ('us-east', 'bar', 2, 2)

query TTII colnames,rowsort
SELECT * FROM uniq_enum
----
r        s    i  j
us-west  foo  1  1
eu-west  bar  2  2

# Upsert into a table with a partial unique constraint.

# Upsert non-conflicting rows.
statement ok
UPSERT INTO uniq_partial_pk VALUES (1, 1, 1), (2, 2, 2), (3, 1, -1)

# Duplicate of a on insert path.
statement error pgcode 23505 pq: duplicate key value violates unique constraint "unique_a"\nDETAIL: Key \(a\)=\(1\) already exists\.
UPSERT INTO uniq_partial_pk VALUES (4, 1, 1)

# Duplicate of a on update path.
statement error pgcode 23505 pq: duplicate key value violates unique constraint "unique_a"\nDETAIL: Key \(a\)=\(1\) already exists\.
UPSERT INTO uniq_partial_pk VALUES (3, 1, 1)

# No duplicate on insert path.
statement ok
UPSERT INTO uniq_partial_pk VALUES (4, 1, -1)

# No duplicate on update path.
statement ok
UPSERT INTO uniq_partial_pk VALUES (2, 1, -1)

query III colnames,rowsort
SELECT * FROM uniq_partial_pk
----
k  a  b
1  1  1
2  1  -1
3  1  -1
4  1  -1

# On conflict do update with a partial unique constraint.

# Clear the table and insert new rows.
statement ok
DELETE FROM uniq_partial;
INSERT INTO uniq_partial VALUES (1, 1), (2, 2), (1, -1)

# Insert non-conflicting rows.
statement ok
INSERT INTO uniq_partial VALUES (3, 3), (1, -2) ON CONFLICT (a) WHERE b > 0 DO UPDATE SET b = -10

# Insert one conflicting row.
statement ok
INSERT INTO uniq_partial VALUES (4, 4), (3, 30) ON CONFLICT (a) WHERE b > 0 DO UPDATE SET b = 33

# Insert two rows that conflict with each other.
statement error pgcode 21000 UPSERT or INSERT...ON CONFLICT command cannot affect row a second time
INSERT INTO uniq_partial VALUES (5, 5), (5, 50) ON CONFLICT (a) WHERE b > 0 DO UPDATE SET b = 33

# Insert a conflicting row that conflicts after update.
statement error pgcode 23505 pq: duplicate key value violates unique constraint "unique_a"\nDETAIL: Key \(a\)=\(1\) already exists\.
INSERT INTO uniq_partial VALUES (4, 40) ON CONFLICT (a) WHERE b > 0 DO UPDATE SET a = 1

# Insert a conflicting row that does not conflict after update.
statement ok
INSERT INTO uniq_partial VALUES (4, 40) ON CONFLICT (a) WHERE b > 0 DO UPDATE SET a = 1, b = -40

query II colnames,rowsort
SELECT * FROM uniq_partial
----
a  b
1  1
1  -1
1  -2
1  -40
2  2
3  33

# Ensure that we do not choose a partial index as the arbiter when there is a
# UNIQUE WITHOUT INDEX constraint.
statement ok
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_and_constraint
----
i
2

# Check that uniqueness violations are detected in a table with UNIQUE indexes
# containing computed columns that are dependent on UNIQUE WITHOUT INDEX
# columns.
statement error pgcode 23505 pq: duplicate key value violates unique constraint "uniq_computed_pk_pkey"\nDETAIL: Key \(c_i_expr, i\)=\('bar', 2\) already exists\.
INSERT INTO uniq_computed_pk (i, s, d) VALUES (1, 'a', 1.0) ON CONFLICT (s) DO UPDATE SET i = 2

statement error pgcode 23505 pq: duplicate key value violates unique constraint "uniq_computed_pk_c_s_s_key"\nDETAIL: Key \(c_s, s\)=\('b', 'b'\) already exists\.
UPSERT INTO uniq_computed_pk (i, s, d) VALUES (3, 'b', 3.0)

statement error pgcode 23505 pq: duplicate key value violates unique constraint "unique_d"\nDETAIL: Key \(d\)=\(2\.00\) already exists\.
UPSERT INTO uniq_computed_pk (i, s, d) VALUES (3, 'c', 2.00)

query ITFTTFT colnames,rowsort
SELECT * FROM uniq_computed_pk
----
i  s  d    c_i_expr  c_s  c_d  c_d_expr
1  a  1.0  bar       a    1.0  1.0
2  b  2.0  bar       b    2.0  2.0


# -- Tests with DELETE --
subtest Delete

# We don't need unique checks with DELETE, but make sure that foreign key
# checks still work.

# Inbound foreign key check should fail.
statement error pgcode 23503 pq: delete on table "uniq_fk_parent" violates foreign key constraint "uniq_fk_child_b_c_fkey" on table "uniq_fk_child"\nDETAIL: Key \(b, c\)=\(2, 2\) is still referenced from table "uniq_fk_child"\.
DELETE FROM uniq_fk_parent WHERE a = 2

statement ok
UPDATE uniq_fk_child SET b = NULL WHERE a = 2

# Inbound foreign key check should still fail.
statement error pgcode 23503 pq: delete on table "uniq_fk_parent" violates foreign key constraint "uniq_fk_child_d_fkey" on table "uniq_fk_child"\nDETAIL: Key \(d\)=\(2\) is still referenced from table "uniq_fk_child"\.
DELETE FROM uniq_fk_parent WHERE a = 2

statement ok
UPDATE uniq_fk_child SET d = NULL WHERE a = 2

# Now this should succeed and set e to NULL due to ON DELETE SET NULL.
statement ok
DELETE FROM uniq_fk_parent WHERE a = 2

query IIIII colnames,rowsort
SELECT * FROM uniq_fk_child
----
a  b     c  d     e
1  1     1  1     1
2  NULL  2  NULL  NULL

subtest GroupByUnique

# Group by UNIQUE WITHOUT INDEX columns which are nullable must not allow
# non-aggregate expressions outside of the grouping columns.
statement error pq: column "b" must appear in the GROUP BY clause or be used in an aggregate function
SELECT b FROM uniq_hidden_pk GROUP BY a

# Group by UNIQUE INDEX columns which are nullable must not allow non-aggregate
# expressions outside of the grouping columns.
statement error pq: column "x" must appear in the GROUP BY clause or be used in an aggregate function
SELECT x FROM uniq GROUP BY v

# Group by UNIQUE WITHOUT INDEX constraint can allow non-aggregate expressions
# outside of the grouping columns if the constraint is not null.
query TI colnames,rowsort
SELECT r, i FROM uniq_enum GROUP BY i
----
r        i
us-west  1
eu-west  2

statement ok
ALTER TABLE uniq_hidden_pk ALTER COLUMN b SET NOT NULL

# Group by UNIQUE WITHOUT INDEX constraint cannot allow non-aggregate
# expressions if any of index columns is nullable.
statement error pq: column "a" must appear in the GROUP BY clause or be used in an aggregate function
SELECT a FROM uniq_hidden_pk GROUP BY b, c

statement ok
ALTER TABLE uniq_hidden_pk ALTER COLUMN c SET NOT NULL

# Group by UNIQUE WITHOUT INDEX constraint can allow non-aggregate expressions
# outside of the grouping columns if the constraint is not nullable.
query II colnames,rowsort
SELECT a,d FROM uniq_hidden_pk GROUP BY b, c
----
a  d
1  1
2  2

# Group by a subset of UNIQUE WITHOUT INDEX columns must not allow non-aggregate
# expressions outside of the grouping columns.
statement error pq: column "a" must appear in the GROUP BY clause or be used in an aggregate function
SELECT a FROM uniq_hidden_pk GROUP BY b

# Group by UNIQUE INDEX constraint cannot allow non-aggregate expressions
# outside of the grouping columns if index columns are nullable.
statement error pq: column "x" must appear in the GROUP BY clause or be used in an aggregate function
SELECT x FROM uniq GROUP BY v

statement ok
ALTER TABLE uniq ALTER COLUMN v SET NOT NULL

# Group by UNIQUE INDEX constraint can allow non-aggregate expressions
# outside of the grouping columns if index columns are not nullable.
query I colnames,rowsort
SELECT x FROM uniq GROUP BY v ORDER BY v
----
x
1
2
3
NULL
5
NULL
2
NULL
1
NULL
NULL
20
NULL
NULL
NULL

subtest multirowValuesInsertFastPath

statement ok
CREATE TABLE t1 (
  pk int PRIMARY KEY,
  pk2 int,
  a int,
  b int,
  j JSON,
  INDEX (a),
  UNIQUE WITHOUT INDEX(b, a),
  INDEX (b,a) STORING(pk2, j),
  INVERTED INDEX (j),
  FAMILY (pk, pk2, a, b)
)

statement ok
INSERT INTO t1 (pk, pk2, a, b, j) VALUES
   (0, 0, 1, 3, '{"a": "b"}');

# This uses insert fast-path. Verify it catches the duplicate value of (b,a).
statement error pq: duplicate key value violates unique constraint "unique_b_a"\nDETAIL: Key \(a, b\)=\(1, 3\) already exists\.
INSERT INTO t1 (pk, pk2, a, b, j) VALUES
   (2, 2, 1, 3, '{"a": "b"}'), (4, 5, 6, 7, '{"a": "b"}');

statement ok
CREATE TABLE multiple_uniq (
  a INT,
  b INT,
  c INT,
  d INT,
  UNIQUE WITHOUT INDEX (b, c),
  UNIQUE WITHOUT INDEX (a, b, d),
  UNIQUE WITHOUT INDEX (a),
  INDEX (a, b, d),
  INDEX (b, c),
  FAMILY (a),
  FAMILY (b),
  FAMILY (c),
  FAMILY (d)
)

# This uses insert fast-path and should succeed.
statement ok
INSERT INTO multiple_uniq
VALUES (1,2,3,4), (5,6,7,8)

# A table with multiple unique without index checks is eligible for insert fast
# path. Verify it catches the duplicate value of (a).
statement error pq: duplicate key value violates unique constraint "unique_a"\nDETAIL: Key \(a\)=\(1\) already exists\.
INSERT INTO multiple_uniq
VALUES (1,12,13,14), (15,16,17,18)

# A table with multiple unique without index checks is eligible for insert fast
# path. Verify it catches the duplicate value of (b,c).
statement error pq: duplicate key value violates unique constraint "unique_b_c"\nDETAIL: Key \(b, c\)=\(2, 3\) already exists\.
INSERT INTO multiple_uniq (a,c,b,d)
VALUES (11,3,2,14), (15,16,17,18)

statement ok
PREPARE p1 AS INSERT INTO multiple_uniq
VALUES ($1, $1, $1, $1), ($2, $2, $2, $2)

# A table with multiple unique without index checks is eligible for parameterized insert fast
# path. Verify it catches the duplicate value of (a).
statement error pq: duplicate key value violates unique constraint "unique_a"\nDETAIL: Key \(a\)=\(1\) already exists\.
EXECUTE p1(1, 2)

statement ok
ALTER TABLE multiple_uniq ADD CONSTRAINT uniq_fk FOREIGN KEY (d) REFERENCES uniq (k) ON DELETE CASCADE;

# A table with multiple unique without index checks and an FK constraint is
# eligible for insert fast path. Verify it catches the foreign key violation on
# (d).
statement error pq: insert on table "multiple_uniq" violates foreign key constraint "uniq_fk"\nDETAIL: Key \(d\)=\(14\) is not present in table "uniq"\.
INSERT INTO multiple_uniq (a,b,c,d)
VALUES (11,12,13,14), (15,16,17,18)

# Regression test for #115377.
statement ok
CREATE TABLE t115377 (
  k INT,
  a INT,
  b INT,
  s TEXT NOT NULL,
  PRIMARY KEY (s, k),
  UNIQUE WITHOUT INDEX (k),
  UNIQUE (s, a, b),
  UNIQUE WITHOUT INDEX (a, b),
  CHECK (s IN ('east', 'west'))
)

statement ok
INSERT INTO t115377 VALUES (2, 0, 0, 'east')

statement error pgcode 23505 duplicate key value violates unique constraint \"unique_k\"
INSERT INTO t115377 VALUES (2, 1, 1, 'east')

# Regression test for #126988.
statement ok
CREATE TABLE t126988 (
  k INT PRIMARY KEY,
  j INT,
  i INT,
  v INT AS (i) VIRTUAL,
  UNIQUE WITHOUT INDEX (i, j),
  INDEX (j, v) STORING (i)
)

statement ok
INSERT INTO t126988 VALUES (1, 10, 200)

statement error pgcode 23505 duplicate key value violates unique constraint \"unique_i_j\"\nDETAIL: Key \(10, 200\) already exists.
INSERT INTO t126988 VALUES (1, 10, 200)

subtest end

# Regression test for hitting a nil pointer in the insert fast path when seeing
# a bool expression in the VALUES clause (#123103).
statement ok
CREATE TABLE t123103 (
	id STRING DEFAULT gen_random_uuid()::STRING NOT NULL,
	r  region NOT NULL DEFAULT 'us-east'::region,
	a  STRING NOT NULL,
	b  BOOL NOT NULL,
	CONSTRAINT tab_pkey PRIMARY KEY (r ASC, id ASC),
	CONSTRAINT tab_id_key UNIQUE WITHOUT INDEX (id ASC),
	CONSTRAINT tab_r_a_b_key UNIQUE (r ASC, a ASC, b ASC),
	CONSTRAINT tab_a_b_key UNIQUE WITHOUT INDEX (a ASC, b ASC)
);
INSERT INTO t123103 (id, a, b) VALUES ('1234567890', 'foo', true);

query TTB
SELECT id, a, b FROM t123103;
----
1234567890  foo  true
