should be it
This commit is contained in:
40
external/duckdb/test/sql/upsert/insert_or_replace.test_slow
vendored
Normal file
40
external/duckdb/test/sql/upsert/insert_or_replace.test_slow
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
# name: test/sql/upsert/insert_or_replace.test_slow
|
||||
# group: [upsert]
|
||||
|
||||
statement ok
|
||||
pragma enable_verification;
|
||||
|
||||
statement ok
|
||||
create table tbl (a integer, b integer unique, c integer default 10);
|
||||
|
||||
statement ok
|
||||
insert into tbl(a,b) values (1,2), (2,1);
|
||||
|
||||
statement ok
|
||||
insert or replace into tbl(a,b,c) values (5,2,20), (10,1,30);
|
||||
|
||||
query III
|
||||
select a,b,c from tbl;
|
||||
----
|
||||
5 2 20
|
||||
10 1 30
|
||||
|
||||
# This should not overwrite the existing value of 'c', as it is explicitly not inserted into
|
||||
statement ok
|
||||
insert or replace into tbl (a,b) values (5,2);
|
||||
|
||||
query I
|
||||
select c from tbl;
|
||||
----
|
||||
20
|
||||
30
|
||||
|
||||
# This should also work when the table is aliased
|
||||
statement ok
|
||||
insert or replace into tbl AS not_tbl (a,b) values (5,2);
|
||||
|
||||
query I
|
||||
select c from tbl;
|
||||
----
|
||||
20
|
||||
30
|
||||
25
external/duckdb/test/sql/upsert/insert_or_replace/pk_and_non_unique_index.test
vendored
Normal file
25
external/duckdb/test/sql/upsert/insert_or_replace/pk_and_non_unique_index.test
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
# name: test/sql/upsert/insert_or_replace/pk_and_non_unique_index.test
|
||||
# group: [insert_or_replace]
|
||||
|
||||
# Single primary key on multiple columns (with non-unique INDEX)
|
||||
statement ok
|
||||
create table tbl(
|
||||
a int,
|
||||
b int,
|
||||
c int,
|
||||
primary key(a,b,c)
|
||||
);
|
||||
|
||||
statement ok
|
||||
create index non_unique on tbl(b);
|
||||
|
||||
statement ok
|
||||
insert or replace into tbl values (1,2,3);
|
||||
|
||||
statement ok
|
||||
insert or replace into tbl values (1,2,3);
|
||||
|
||||
query III
|
||||
select * from tbl;
|
||||
----
|
||||
1 2 3
|
||||
22
external/duckdb/test/sql/upsert/insert_or_replace/primary_key.test
vendored
Normal file
22
external/duckdb/test/sql/upsert/insert_or_replace/primary_key.test
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
# name: test/sql/upsert/insert_or_replace/primary_key.test
|
||||
# group: [insert_or_replace]
|
||||
|
||||
# Single primary key on multiple columns
|
||||
statement ok
|
||||
create table tbl(
|
||||
a int,
|
||||
b int,
|
||||
c int,
|
||||
primary key(a,b,c)
|
||||
);
|
||||
|
||||
statement ok
|
||||
insert or replace into tbl values (1,2,3);
|
||||
|
||||
statement ok
|
||||
insert or replace into tbl values (1,2,3);
|
||||
|
||||
query III
|
||||
select * from tbl;
|
||||
----
|
||||
1 2 3
|
||||
24
external/duckdb/test/sql/upsert/insert_or_replace/returning.test
vendored
Normal file
24
external/duckdb/test/sql/upsert/insert_or_replace/returning.test
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
# name: test/sql/upsert/insert_or_replace/returning.test
|
||||
# group: [insert_or_replace]
|
||||
|
||||
statement ok
|
||||
create table foo(
|
||||
bar text primary key,
|
||||
baz bigint,
|
||||
);
|
||||
|
||||
query I
|
||||
insert or replace into foo(bar, baz) values ('baz', 1) returning bar;
|
||||
----
|
||||
baz
|
||||
|
||||
query I
|
||||
insert or replace into foo(bar, baz) values ('baz', 2) returning bar;
|
||||
----
|
||||
baz
|
||||
|
||||
query I
|
||||
insert or replace into foo(bar, baz) values ('baz', 1), ('bar', 2) returning bar;
|
||||
----
|
||||
baz
|
||||
bar
|
||||
31
external/duckdb/test/sql/upsert/insert_or_replace/returning_nothing.test
vendored
Normal file
31
external/duckdb/test/sql/upsert/insert_or_replace/returning_nothing.test
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
# name: test/sql/upsert/insert_or_replace/returning_nothing.test
|
||||
# group: [insert_or_replace]
|
||||
|
||||
statement ok
|
||||
CREATE SEQUENCE seq START 1;
|
||||
|
||||
statement ok
|
||||
CREATE TABLE bug (
|
||||
id INTEGER PRIMARY KEY DEFAULT NEXTVAL('seq'),
|
||||
name VARCHAR
|
||||
);
|
||||
|
||||
statement ok
|
||||
CREATE UNIQUE INDEX idx ON bug (name);
|
||||
|
||||
query I
|
||||
INSERT OR IGNORE INTO bug VALUES
|
||||
(DEFAULT, 'toto') RETURNING(id);
|
||||
----
|
||||
1
|
||||
|
||||
query I
|
||||
INSERT OR IGNORE INTO bug VALUES
|
||||
(DEFAULT, 'toto') RETURNING(id);
|
||||
----
|
||||
|
||||
query I
|
||||
INSERT OR IGNORE INTO bug VALUES
|
||||
(DEFAULT, 'toto'), (DEFAULT, 'yoyo') RETURNING(id);
|
||||
----
|
||||
4
|
||||
27
external/duckdb/test/sql/upsert/insert_or_replace/unique_and_non_unique_index.test
vendored
Normal file
27
external/duckdb/test/sql/upsert/insert_or_replace/unique_and_non_unique_index.test
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
# name: test/sql/upsert/insert_or_replace/unique_and_non_unique_index.test
|
||||
# group: [insert_or_replace]
|
||||
|
||||
# Single UNIQUE INDEX + non-unique INDEX
|
||||
statement ok
|
||||
create table tbl(
|
||||
a int,
|
||||
b int,
|
||||
c int
|
||||
);
|
||||
|
||||
statement ok
|
||||
create UNIQUE index "unique" on tbl(a, b);
|
||||
|
||||
statement ok
|
||||
create index non_unique on tbl(a, b);
|
||||
|
||||
statement ok
|
||||
insert or replace into tbl values (1,2,3);
|
||||
|
||||
statement ok
|
||||
insert or replace into tbl values (1,2,3);
|
||||
|
||||
query III
|
||||
select * from tbl;
|
||||
----
|
||||
1 2 3
|
||||
33
external/duckdb/test/sql/upsert/insert_or_replace/unique_constraint.test
vendored
Normal file
33
external/duckdb/test/sql/upsert/insert_or_replace/unique_constraint.test
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
# name: test/sql/upsert/insert_or_replace/unique_constraint.test
|
||||
# group: [insert_or_replace]
|
||||
|
||||
# Single UNIQUE CONSTRAINT
|
||||
statement ok
|
||||
create table tbl(
|
||||
a int unique,
|
||||
b int
|
||||
);
|
||||
|
||||
statement ok
|
||||
insert or replace into tbl values(1, 2);
|
||||
|
||||
statement ok
|
||||
insert or replace into tbl values(1, 2);
|
||||
|
||||
query II
|
||||
select * from tbl;
|
||||
----
|
||||
1 2
|
||||
|
||||
# Multiple UNIQUE CONSTRAINTs
|
||||
statement ok
|
||||
create table multiple_unique(
|
||||
a int unique,
|
||||
b int unique,
|
||||
c int
|
||||
);
|
||||
|
||||
statement error
|
||||
insert or replace into multiple_unique values(1, 2, 3);
|
||||
----
|
||||
Binder Error: Conflict target has to be provided for a DO UPDATE operation when the table has multiple UNIQUE/PRIMARY KEY constraints
|
||||
36
external/duckdb/test/sql/upsert/insert_or_replace/unique_constraint_and_non_unique_index.test
vendored
Normal file
36
external/duckdb/test/sql/upsert/insert_or_replace/unique_constraint_and_non_unique_index.test
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
# name: test/sql/upsert/insert_or_replace/unique_constraint_and_non_unique_index.test
|
||||
# group: [insert_or_replace]
|
||||
|
||||
# Single UNIQUE CONSTRAINT
|
||||
statement ok
|
||||
create table tbl(
|
||||
a int unique,
|
||||
b int
|
||||
);
|
||||
|
||||
statement ok
|
||||
create index non_unique on tbl(a, b);
|
||||
|
||||
statement ok
|
||||
insert or replace into tbl values(1, 2);
|
||||
|
||||
statement ok
|
||||
insert or replace into tbl values(1, 2);
|
||||
|
||||
query II
|
||||
select * from tbl;
|
||||
----
|
||||
1 2
|
||||
|
||||
# Multiple UNIQUE CONSTRAINTs
|
||||
statement ok
|
||||
create table multiple_unique(
|
||||
a int unique,
|
||||
b int unique,
|
||||
c int
|
||||
);
|
||||
|
||||
statement error
|
||||
insert or replace into multiple_unique values(1, 2, 3);
|
||||
----
|
||||
Binder Error: Conflict target has to be provided for a DO UPDATE operation when the table has multiple UNIQUE/PRIMARY KEY constraints
|
||||
35
external/duckdb/test/sql/upsert/insert_or_replace/unique_index.test
vendored
Normal file
35
external/duckdb/test/sql/upsert/insert_or_replace/unique_index.test
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
# name: test/sql/upsert/insert_or_replace/unique_index.test
|
||||
# description: Test INSERT OR REPLACE with a unique index.
|
||||
# group: [insert_or_replace]
|
||||
|
||||
statement ok
|
||||
PRAGMA enable_verification
|
||||
|
||||
# Single UNIQUE INDEX
|
||||
|
||||
statement ok
|
||||
CREATE TABLE tbl(a INT, b INT, c INT);
|
||||
|
||||
statement ok
|
||||
CREATE UNIQUE INDEX "unique" ON tbl(a, b);
|
||||
|
||||
statement ok
|
||||
INSERT OR REPLACE INTO tbl VALUES (1, 2, 3);
|
||||
|
||||
statement ok
|
||||
INSERT OR REPLACE INTO tbl VALUES (1, 2, 3);
|
||||
|
||||
query III
|
||||
SELECT * FROM tbl;
|
||||
----
|
||||
1 2 3
|
||||
|
||||
# Multiple UNIQUE indexes.
|
||||
|
||||
statement ok
|
||||
CREATE UNIQUE INDEX idx3 ON tbl(b, c);
|
||||
|
||||
statement error
|
||||
INSERT OR REPLACE INTO tbl VALUES (1, 2, 3);
|
||||
----
|
||||
<REGEX>:Binder Error.*Conflict target has to be provided for a DO UPDATE operation when the table has multiple UNIQUE/PRIMARY KEY constraints.*
|
||||
34
external/duckdb/test/sql/upsert/minimal_reproducable_example.test
vendored
Normal file
34
external/duckdb/test/sql/upsert/minimal_reproducable_example.test
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
# name: test/sql/upsert/minimal_reproducable_example.test
|
||||
# group: [upsert]
|
||||
|
||||
statement ok
|
||||
pragma enable_verification;
|
||||
|
||||
# Create a table with 3 columns, 2 of which are indexed on
|
||||
statement ok
|
||||
create or replace table tbl(
|
||||
i integer PRIMARY KEY,
|
||||
j integer UNIQUE,
|
||||
k integer
|
||||
);
|
||||
|
||||
# Add 3 rows
|
||||
statement ok
|
||||
insert into tbl VALUES (1, 10, 1), (2, 20, 1), (3, 30, 2);
|
||||
|
||||
query III
|
||||
select * from tbl;
|
||||
----
|
||||
1 10 1
|
||||
2 20 1
|
||||
3 30 2
|
||||
|
||||
statement ok
|
||||
insert into tbl VALUES (3,5,1) ON CONFLICT (i) DO UPDATE SET k = k + excluded.k;
|
||||
|
||||
query III
|
||||
select * from tbl;
|
||||
----
|
||||
1 10 1
|
||||
2 20 1
|
||||
3 30 3
|
||||
13
external/duckdb/test/sql/upsert/no_complex_default.test
vendored
Normal file
13
external/duckdb/test/sql/upsert/no_complex_default.test
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
# name: test/sql/upsert/no_complex_default.test
|
||||
# group: [upsert]
|
||||
|
||||
statement ok
|
||||
pragma enable_verification;
|
||||
|
||||
statement ok
|
||||
create or replace table tbl (a integer default 3);
|
||||
|
||||
statement error
|
||||
insert into tbl VALUES ((3+DEFAULT));
|
||||
----
|
||||
Binder Error: DEFAULT is not allowed here!
|
||||
109
external/duckdb/test/sql/upsert/postgres/composite_key.test
vendored
Normal file
109
external/duckdb/test/sql/upsert/postgres/composite_key.test
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
# name: test/sql/upsert/postgres/composite_key.test
|
||||
# group: [postgres]
|
||||
|
||||
statement ok
|
||||
pragma enable_verification;
|
||||
|
||||
# insert...on conflict do unique index inference
|
||||
|
||||
statement ok
|
||||
create table insertconflicttest(
|
||||
key int4,
|
||||
fruit text,
|
||||
other int4,
|
||||
unique (key, fruit)
|
||||
);
|
||||
|
||||
# fails
|
||||
|
||||
statement error
|
||||
insert into insertconflicttest values(0, 'Crowberry', 0) on conflict (key) do nothing;
|
||||
----
|
||||
|
||||
statement error
|
||||
insert into insertconflicttest values(0, 'Crowberry', 0) on conflict (fruit) do nothing;
|
||||
----
|
||||
|
||||
# succeeds
|
||||
|
||||
statement ok
|
||||
insert into insertconflicttest values(0, 'Crowberry', 0) on conflict (key, fruit) do nothing;
|
||||
|
||||
statement ok
|
||||
insert into insertconflicttest values(0, 'Crowberry', 0) on conflict (fruit, key, fruit, key) do nothing;
|
||||
|
||||
## -- We explicitly don't support a subquery in the WHERE clause currently -- ##
|
||||
statement error
|
||||
insert into insertconflicttest
|
||||
values (0, 'Crowberry', 0) on conflict (key, fruit) do update set other = 1 where exists (select 1 from insertconflicttest ii where ii.key = excluded.key);
|
||||
----
|
||||
DO UPDATE SET clause cannot contain a subquery
|
||||
|
||||
# inference succeeds:
|
||||
|
||||
statement ok
|
||||
insert into insertconflicttest values (7, 'Raspberry', 0) on conflict (key, fruit) do update set other = 1
|
||||
|
||||
statement ok
|
||||
insert into insertconflicttest values (8, 'Lime', 0) on conflict (fruit, key) do update set other = 1
|
||||
|
||||
# inference fails:
|
||||
|
||||
statement error
|
||||
insert into insertconflicttest values (9, 'Banana', 0) on conflict (key) do update set other = 1
|
||||
----
|
||||
|
||||
statement error
|
||||
insert into insertconflicttest values (10, 'Blueberry', 0) on conflict (key, key, key) do update set other = 1
|
||||
----
|
||||
|
||||
## -- This fails on postgres for some reason? -- ##
|
||||
statement ok
|
||||
insert into insertconflicttest values (11, 'Cherry', 0) on conflict (key, fruit) do update set other = 1
|
||||
|
||||
## -- This fails on postgres for some reason? -- ##
|
||||
statement ok
|
||||
insert into insertconflicttest values (12, 'Date', 0) on conflict (fruit, key) do update set other = 1
|
||||
|
||||
# Partial index tests, no inference predicate specified
|
||||
statement error
|
||||
create unique index part_comp_key_index on insertconflicttest(key, fruit) where key < 5;
|
||||
----
|
||||
Creating partial indexes is not supported currently
|
||||
|
||||
statement error
|
||||
create unique index expr_part_comp_key_index on insertconflicttest(key, fruit) where key < 5;
|
||||
----
|
||||
Creating partial indexes is not supported currently
|
||||
|
||||
# Expression index tests
|
||||
statement ok
|
||||
create unique index expr_key_index on insertconflicttest(fruit);
|
||||
|
||||
# inference succeeds:
|
||||
|
||||
statement ok
|
||||
insert into insertconflicttest values (20, 'Quince', 0) on conflict (fruit) do update set other = 1
|
||||
|
||||
statement ok
|
||||
insert into insertconflicttest values (21, 'Pomegranate', 0) on conflict (fruit, fruit) do update set other = 1
|
||||
|
||||
|
||||
# Expression index tests (with regular column)
|
||||
statement ok
|
||||
create unique index expr_comp_key_index on insertconflicttest(key, fruit);
|
||||
|
||||
statement ok
|
||||
create unique index tricky_expr_comp_key_index on insertconflicttest(key, fruit, fruit);
|
||||
|
||||
# inference succeeds:
|
||||
|
||||
statement ok
|
||||
insert into insertconflicttest values (24, 'Plum', 0) on conflict (key, fruit) do update set other = 1
|
||||
|
||||
statement ok
|
||||
insert into insertconflicttest values (25, 'Peach', 0) on conflict (fruit, key) do update set other = 1
|
||||
# Should not infer "tricky_expr_comp_key_index" index:
|
||||
|
||||
statement ok
|
||||
insert into insertconflicttest values (26, 'Fig', 0) on conflict (fruit, key, fruit, key) do update set other = 1
|
||||
56
external/duckdb/test/sql/upsert/postgres/non_spurious_duplicate_violation.test
vendored
Normal file
56
external/duckdb/test/sql/upsert/postgres/non_spurious_duplicate_violation.test
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
# name: test/sql/upsert/postgres/non_spurious_duplicate_violation.test
|
||||
# group: [postgres]
|
||||
|
||||
statement ok
|
||||
pragma enable_verification;
|
||||
|
||||
# insert...on conflict do unique index inference
|
||||
|
||||
statement ok
|
||||
create table insertconflicttest(
|
||||
key int4,
|
||||
fruit text,
|
||||
other int4,
|
||||
unique (key),
|
||||
unique (fruit)
|
||||
);
|
||||
|
||||
statement ok
|
||||
insert into insertconflicttest values (25, 'Fig', 0) on conflict (fruit) do update set other = 1
|
||||
|
||||
# Succeeds
|
||||
|
||||
statement ok
|
||||
insert into insertconflicttest values (23, 'Blackberry', 0) on conflict (key) do update set other = 1 where fruit like '%berry'
|
||||
|
||||
# Test that wholerow references to ON CONFLICT's EXCLUDED work
|
||||
|
||||
# Succeeds, updates existing row:
|
||||
|
||||
statement ok
|
||||
insert into insertconflicttest as i values (23, 'Jackfruit', 0) on conflict (key) do update set other = 1
|
||||
# No update this time, though:
|
||||
|
||||
statement ok
|
||||
insert into insertconflicttest as i values (23, 'Jackfruit', 0) on conflict (key) do update set other = 1
|
||||
# Predicate changed to require match rather than non-match, so updates once more:
|
||||
|
||||
statement ok
|
||||
insert into insertconflicttest as i values (23, 'Jackfruit', 0) on conflict (key) do update set other = 1
|
||||
# Assign:
|
||||
|
||||
statement ok
|
||||
insert into insertconflicttest as i values (23, 'Avocado', 0) on conflict (key) do update set other = 1
|
||||
# deparse whole row var in WHERE and SET clauses:
|
||||
|
||||
statement ok
|
||||
insert into insertconflicttest as i values (23, 'Avocado', 0) on conflict (key) do update set other = 1
|
||||
|
||||
statement ok
|
||||
insert into insertconflicttest as i values (23, 'Avocado', 0) on conflict (key) do update set other = 1
|
||||
|
||||
|
||||
# Cleanup
|
||||
|
||||
statement ok
|
||||
drop table insertconflicttest;
|
||||
207
external/duckdb/test/sql/upsert/postgres/planner_preprocessing.test
vendored
Normal file
207
external/duckdb/test/sql/upsert/postgres/planner_preprocessing.test
vendored
Normal file
@@ -0,0 +1,207 @@
|
||||
# name: test/sql/upsert/postgres/planner_preprocessing.test
|
||||
# group: [postgres]
|
||||
|
||||
statement ok
|
||||
pragma enable_verification;
|
||||
|
||||
# ******************************************************************
|
||||
# * *
|
||||
# * Test inheritance (example taken from tutorial) *
|
||||
# * *
|
||||
# ******************************************************************
|
||||
|
||||
statement ok
|
||||
create table cities (
|
||||
name text,
|
||||
population float8,
|
||||
altitude int,
|
||||
unique (name)
|
||||
);
|
||||
|
||||
statement ok
|
||||
create table capitals (
|
||||
name text,
|
||||
population float8,
|
||||
altitude int,
|
||||
state char(2),
|
||||
unique (name)
|
||||
);
|
||||
|
||||
# Create unique indexes. Due to a general limitation of inheritance,
|
||||
# uniqueness is only enforced per-relation. Unique index inference
|
||||
# specification will do the right thing, though.
|
||||
|
||||
# prepopulate the tables.
|
||||
|
||||
statement ok
|
||||
insert into cities values ('San Francisco', 7.24E+5, 63);
|
||||
|
||||
statement ok
|
||||
insert into cities values ('Las Vegas', 2.583E+5, 2174);
|
||||
|
||||
statement ok
|
||||
insert into cities values ('Mariposa', 1200, 1953);
|
||||
|
||||
|
||||
statement ok
|
||||
insert into capitals values ('Sacramento', 3.694E+5, 30, 'CA');
|
||||
|
||||
statement ok
|
||||
insert into capitals values ('Madison', 1.913E+5, 845, 'WI');
|
||||
|
||||
# Tests proper for inheritance:
|
||||
query IIII
|
||||
select * from capitals;
|
||||
----
|
||||
Sacramento 369400.0 30 CA
|
||||
Madison 191300.0 845 WI
|
||||
|
||||
# Succeeds:
|
||||
|
||||
statement ok
|
||||
insert into cities values ('Las Vegas', 2.583E+5, 2174) on conflict do nothing;
|
||||
|
||||
statement ok
|
||||
insert into capitals values ('Sacramento', 4664.E+5, 30, 'CA') on conflict (name) do update set population = excluded.population;
|
||||
# Wrong "Sacramento", so do nothing:
|
||||
|
||||
statement ok
|
||||
insert into capitals values ('Sacramento', 50, 2267, 'NE') on conflict (name) do nothing;
|
||||
|
||||
query IIII
|
||||
select * from capitals;
|
||||
----
|
||||
Sacramento 466400000.0 30 CA
|
||||
Madison 191300.0 845 WI
|
||||
|
||||
statement ok
|
||||
insert into cities values ('Las Vegas', 5.83E+5, 2001) on conflict (name) do update set population = excluded.population, altitude = excluded.altitude;
|
||||
|
||||
query IIII
|
||||
select rowid, * from cities;
|
||||
----
|
||||
0 San Francisco 724000.0 63
|
||||
1 Las Vegas 583000.0 2001
|
||||
2 Mariposa 1200.0 1953
|
||||
|
||||
statement ok
|
||||
insert into capitals values ('Las Vegas', 5.83E+5, 2222, 'NV') on conflict (name) do update set population = excluded.population;
|
||||
# Capitals will contain new capital, Las Vegas:
|
||||
|
||||
query IIII
|
||||
select * from capitals;
|
||||
----
|
||||
Sacramento 466400000.0 30 CA
|
||||
Madison 191300.0 845 WI
|
||||
Las Vegas 583000.0 2222 NV
|
||||
|
||||
# Cities contains two instances of "Las Vegas", since unique constraints don't
|
||||
# work across inheritance:
|
||||
|
||||
query IIII
|
||||
select rowid, * from cities;
|
||||
----
|
||||
0 San Francisco 724000.0 63
|
||||
1 Las Vegas 583000.0 2001
|
||||
2 Mariposa 1200.0 1953
|
||||
|
||||
# This only affects "cities" version of "Las Vegas":
|
||||
|
||||
statement ok
|
||||
insert into cities values ('Las Vegas', 5.86E+5, 2223) on conflict (name) do update set population = excluded.population, altitude = excluded.altitude;
|
||||
select rowid, * from cities;
|
||||
|
||||
# clean up
|
||||
|
||||
statement ok
|
||||
drop table capitals;
|
||||
|
||||
statement ok
|
||||
drop table cities;
|
||||
|
||||
|
||||
# Make sure a table named excluded is handled properly
|
||||
|
||||
statement ok
|
||||
create table excluded(key int primary key, data text);
|
||||
|
||||
statement ok
|
||||
insert into excluded values(1, '1');
|
||||
|
||||
# error, ambiguous
|
||||
statement error
|
||||
insert into excluded values(1, '2') on conflict (key) do update set data = excluded.data RETURNING *;
|
||||
----
|
||||
|
||||
# ok, aliased
|
||||
statement ok
|
||||
insert into excluded AS target values(1, '2') on conflict (key) do update set data = excluded.data RETURNING *;
|
||||
|
||||
# ok, aliased
|
||||
statement ok
|
||||
insert into excluded AS target values(1, '2') on conflict (key) do update set data = target.data RETURNING *;
|
||||
|
||||
## -- We don't support excluded in RETURNING, also, this is ambiguous??? -- ##
|
||||
# make sure excluded isn't a problem in returning clause
|
||||
statement error
|
||||
insert into excluded values(1, '2') on conflict (key) do update set data = 3 RETURNING excluded.*;
|
||||
----
|
||||
Ambiguous reference to table "excluded"
|
||||
|
||||
# clean up
|
||||
statement ok
|
||||
drop table excluded;
|
||||
|
||||
|
||||
# check that references to columns after dropped columns are handled correctly
|
||||
|
||||
statement ok
|
||||
create table dropcol(key int primary key, drop1 int, keep1 text, drop2 numeric, keep2 float);
|
||||
|
||||
statement ok
|
||||
insert into dropcol(key, drop1, keep1, drop2, keep2) values(1, 1, '1', '1', 1);
|
||||
# set using excluded
|
||||
|
||||
statement ok
|
||||
insert into dropcol(key, drop1, keep1, drop2, keep2) values(1, 2, '2', '2', 2) on conflict(key)
|
||||
do update set drop1 = excluded.drop1, keep1 = excluded.keep1, drop2 = excluded.drop2, keep2 = excluded.keep2
|
||||
where excluded.drop1 is not null and excluded.keep1 is not null and excluded.drop2 is not null and excluded.keep2 is not null
|
||||
and dropcol.drop1 is not null and dropcol.keep1 is not null and dropcol.drop2 is not null and dropcol.keep2 is not null
|
||||
returning *;
|
||||
;
|
||||
# set using existing table
|
||||
|
||||
statement ok
|
||||
insert into dropcol(key, drop1, keep1, drop2, keep2) values(1, 3, '3', '3', 3) on conflict(key)
|
||||
do update set drop1 = dropcol.drop1, keep1 = dropcol.keep1, drop2 = dropcol.drop2, keep2 = dropcol.keep2
|
||||
returning *;
|
||||
;
|
||||
|
||||
statement ok
|
||||
alter table dropcol
|
||||
drop column drop1;
|
||||
|
||||
statement ok
|
||||
alter table dropcol
|
||||
drop column drop2;
|
||||
|
||||
# set using excluded
|
||||
|
||||
statement ok
|
||||
insert into dropcol(key, keep1, keep2) values(1, '4', 4) on conflict(key)
|
||||
do update set keep1 = excluded.keep1, keep2 = excluded.keep2
|
||||
where excluded.keep1 is not null and excluded.keep2 is not null
|
||||
and dropcol.keep1 is not null and dropcol.keep2 is not null
|
||||
returning *;
|
||||
;
|
||||
# set using existing table
|
||||
|
||||
statement ok
|
||||
insert into dropcol(key, keep1, keep2) values(1, '5', 5) on conflict(key)
|
||||
do update set keep1 = dropcol.keep1, keep2 = dropcol.keep2
|
||||
returning *;
|
||||
;
|
||||
|
||||
|
||||
statement ok
|
||||
DROP TABLE dropcol;
|
||||
111
external/duckdb/test/sql/upsert/postgres/single_key.test
vendored
Normal file
111
external/duckdb/test/sql/upsert/postgres/single_key.test
vendored
Normal file
@@ -0,0 +1,111 @@
|
||||
# name: test/sql/upsert/postgres/single_key.test
|
||||
# group: [postgres]
|
||||
|
||||
statement ok
|
||||
pragma enable_verification;
|
||||
|
||||
# insert...on conflict do unique index inference
|
||||
|
||||
statement ok
|
||||
create table insertconflicttest(
|
||||
key int4,
|
||||
fruit text,
|
||||
unique (key)
|
||||
);
|
||||
|
||||
# Explain tests
|
||||
|
||||
statement ok
|
||||
insert into insertconflicttest values (0, 'Bilberry') on conflict (key) do update set fruit = excluded.fruit;
|
||||
# Should display qual actually attributable to internal sequential scan:
|
||||
|
||||
statement ok
|
||||
insert into insertconflicttest values (0, 'Bilberry') on conflict (key) do update set fruit = excluded.fruit where insertconflicttest.fruit != 'Cawesh';
|
||||
# With EXCLUDED.* expression in scan node:
|
||||
|
||||
statement ok
|
||||
insert into insertconflicttest values(0, 'Crowberry') on conflict (key) do update set fruit = excluded.fruit where excluded.fruit != 'Elderberry';
|
||||
# Does the same, but JSON format shows "Conflict Arbiter Index" as JSON array:
|
||||
statement ok
|
||||
insert into insertconflicttest values (0, 'Bilberry') on conflict (key) do update set fruit = excluded.fruit where insertconflicttest.fruit != 'Lime' returning *;
|
||||
|
||||
# Fails (no unique index inference specification, required for do update variant):
|
||||
|
||||
## -- We accept this because there is only 1 Index on the table -- ##
|
||||
statement ok
|
||||
insert into insertconflicttest values (1, 'Apple') on conflict do update set fruit = excluded.fruit;
|
||||
|
||||
# inference succeeds:
|
||||
|
||||
statement ok
|
||||
insert into insertconflicttest values (1, 'Apple') on conflict (key) do update set fruit = excluded.fruit;
|
||||
|
||||
statement ok
|
||||
insert into insertconflicttest values (2, 'Orange') on conflict (key, key, key) do update set fruit = excluded.fruit;
|
||||
|
||||
# Succeed, since multi-assignment does not involve subquery:
|
||||
|
||||
statement ok
|
||||
INSERT INTO insertconflicttest VALUES (1, 'Apple'), (2, 'Orange')
|
||||
ON CONFLICT (key) DO UPDATE SET fruit = excluded.fruit, key = excluded.key;
|
||||
|
||||
# Give good diagnostic message when EXCLUDED.* spuriously referenced from
|
||||
# RETURNING:
|
||||
|
||||
## -- We don't support 'excluded' qualified columns in the RETURNING clause yet -- ##
|
||||
statement error
|
||||
insert into insertconflicttest values (1, 'Apple') on conflict (key) do update set fruit = excluded.fruit RETURNING excluded.fruit;
|
||||
----
|
||||
<REGEX>:.*Not implemented Error.*not supported in the RETURNING clause yet.*
|
||||
|
||||
# Only suggest <table>.* column when inference element misspelled:
|
||||
|
||||
statement error
|
||||
insert into insertconflicttest values (1, 'Apple') on conflict (keyy) do update set fruit = excluded.fruit;
|
||||
----
|
||||
<REGEX>:.*Binder Error.*Table "insertconflicttest" does not have a column.*
|
||||
|
||||
# Have useful HINT for EXCLUDED.* RTE within UPDATE:
|
||||
|
||||
statement error
|
||||
insert into insertconflicttest values (1, 'Apple') on conflict (key) do update set fruit = excluded.fruitt;
|
||||
----
|
||||
<REGEX>:.*Binder Error.*does not have a column named "fruitt".*
|
||||
|
||||
# inference fails:
|
||||
|
||||
statement error
|
||||
insert into insertconflicttest values (3, 'Kiwi') on conflict (key, fruit) do update set fruit = excluded.fruit;
|
||||
----
|
||||
<REGEX>:.*Binder Error.*not referenced by a UNIQUE/PRIMARY KEY CONSTRAINT or INDEX.*
|
||||
|
||||
statement error
|
||||
insert into insertconflicttest values (4, 'Mango') on conflict (fruit, key) do update set fruit = excluded.fruit;
|
||||
----
|
||||
<REGEX>:.*Binder Error.*not referenced by a UNIQUE/PRIMARY KEY CONSTRAINT or INDEX.*
|
||||
|
||||
statement error
|
||||
insert into insertconflicttest values (5, 'Lemon') on conflict (fruit) do update set fruit = excluded.fruit;
|
||||
----
|
||||
<REGEX>:.*Binder Error.*not referenced by a UNIQUE/PRIMARY KEY CONSTRAINT or INDEX.*
|
||||
|
||||
statement error
|
||||
insert into insertconflicttest values (6, 'Passionfruit') on conflict (fruit) do update set fruit = excluded.fruit;
|
||||
----
|
||||
<REGEX>:.*Binder Error.*not referenced by a UNIQUE/PRIMARY KEY CONSTRAINT or INDEX.*
|
||||
|
||||
# Check the target relation can be aliased
|
||||
|
||||
statement ok
|
||||
insert into insertconflicttest AS ict values (6, 'Passionfruit') on conflict (key) do update set fruit = excluded.fruit;
|
||||
# ok, no reference to target table
|
||||
|
||||
statement ok
|
||||
insert into insertconflicttest AS ict values (6, 'Passionfruit') on conflict (key) do update set fruit = ict.fruit;
|
||||
# ok, alias
|
||||
|
||||
# error, references aliased away name
|
||||
statement error
|
||||
insert into insertconflicttest AS ict values (6, 'Passionfruit') on conflict (key) do update set fruit = insertconflicttest.fruit;
|
||||
----
|
||||
<REGEX>:.*Binder Error.*Referenced table.*not found.*
|
||||
103
external/duckdb/test/sql/upsert/test_big_insert.test
vendored
Normal file
103
external/duckdb/test/sql/upsert/test_big_insert.test
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
# name: test/sql/upsert/test_big_insert.test
|
||||
# description: Test insert into statements
|
||||
# group: [upsert]
|
||||
|
||||
statement ok
|
||||
PRAGMA enable_verification;
|
||||
|
||||
statement ok
|
||||
SET preserve_insertion_order = false;
|
||||
|
||||
statement ok
|
||||
CREATE TABLE integers(
|
||||
i INT UNIQUE,
|
||||
j INT DEFAULT 0,
|
||||
k INT DEFAULT 0
|
||||
);
|
||||
|
||||
statement ok
|
||||
INSERT INTO integers(i) SELECT i FROM range(5000) tbl(i);
|
||||
|
||||
query I
|
||||
SELECT COUNT(*) FROM integers
|
||||
----
|
||||
5000
|
||||
|
||||
# All tuples hit a conflict - DO NOTHING.
|
||||
statement ok
|
||||
INSERT INTO integers SELECT * FROM integers ON CONFLICT DO NOTHING;
|
||||
|
||||
# All tuples hit a conflict - DO UPDATE.
|
||||
statement ok
|
||||
INSERT INTO integers SELECT * FROM integers ON CONFLICT DO UPDATE SET j = 10;
|
||||
|
||||
# All 'j' entries are changed to 10.
|
||||
query I
|
||||
SELECT COUNT(*) FILTER (WHERE j = 10) FROM integers
|
||||
----
|
||||
5000
|
||||
|
||||
statement ok
|
||||
INSERT INTO integers(i, j) SELECT i % 5, i FROM range(4995, 5000) tbl(i) ON CONFLICT DO UPDATE SET j = excluded.j, k = excluded.i;
|
||||
|
||||
query I
|
||||
SELECT j FROM integers LIMIT 5;
|
||||
----
|
||||
4995
|
||||
4996
|
||||
4997
|
||||
4998
|
||||
4999
|
||||
|
||||
# This is the worst conflicting rowid pattern we could have.
|
||||
# Every odd-indexed insert tuple conflicts with a row at the start of the existing tuples.
|
||||
# And every even-indexed insert tuple conflicts with a row at the end of the existing tuples.
|
||||
statement ok
|
||||
INSERT INTO integers(i, j)
|
||||
SELECT CASE WHEN i % 2 = 0
|
||||
THEN 4999 - (i // 2)
|
||||
ELSE i - ((i // 2) + 1)
|
||||
END, i
|
||||
FROM range(5000) tbl(i)
|
||||
ON CONFLICT DO UPDATE SET j = excluded.j;
|
||||
|
||||
# This shows that the odd-indexed insert tuples conflicted with the first rows.
|
||||
query I
|
||||
SELECT j FROM integers LIMIT 5;
|
||||
----
|
||||
1
|
||||
3
|
||||
5
|
||||
7
|
||||
9
|
||||
|
||||
# This shows that the even-indexed insert tuples conflicted with the last rows.
|
||||
query I
|
||||
SELECT j FROM integers LIMIT 5 OFFSET 4995;
|
||||
----
|
||||
8
|
||||
6
|
||||
4
|
||||
2
|
||||
0
|
||||
|
||||
# Reset j.
|
||||
statement ok
|
||||
UPDATE integers SET j = 0;
|
||||
|
||||
# Only set j if both the existing tuple and the insert tuple are even.
|
||||
statement ok
|
||||
INSERT INTO integers(i, j)
|
||||
SELECT CASE WHEN i % 2 = 0
|
||||
THEN 4999 - (i // 2)
|
||||
ELSE i - ((i // 2) + 1)
|
||||
END, i
|
||||
FROM range(5000) tbl(i)
|
||||
ON CONFLICT DO UPDATE SET j = excluded.j
|
||||
WHERE i % 2 = 0 AND excluded.j % 2 = 0;
|
||||
|
||||
# The DO UPDATE WHERE clause is only true for a quarter of the cases.
|
||||
query I
|
||||
SELECT COUNT(j) FILTER (WHERE j != 0) FROM integers;
|
||||
----
|
||||
1250
|
||||
28
external/duckdb/test/sql/upsert/test_big_insert_no_vector_verification.test
vendored
Normal file
28
external/duckdb/test/sql/upsert/test_big_insert_no_vector_verification.test
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
# name: test/sql/upsert/test_big_insert_no_vector_verification.test
|
||||
# description: Test ON CONFLICT statement on the same conflicting row.
|
||||
# group: [upsert]
|
||||
|
||||
require vector_size 2048
|
||||
|
||||
statement ok
|
||||
PRAGMA enable_verification;
|
||||
|
||||
statement ok
|
||||
SET preserve_insertion_order = false;
|
||||
|
||||
statement ok
|
||||
CREATE TABLE integers(
|
||||
i INT UNIQUE,
|
||||
j INT DEFAULT 0,
|
||||
k INT DEFAULT 0
|
||||
);
|
||||
|
||||
statement ok
|
||||
INSERT INTO integers(i) SELECT i FROM range(5000) tbl(i);
|
||||
|
||||
statement ok
|
||||
INSERT INTO integers(i, j)
|
||||
SELECT i % 5, i
|
||||
FROM range(5000) tbl(i) ON CONFLICT DO UPDATE SET
|
||||
j = excluded.j,
|
||||
k = excluded.i;
|
||||
48
external/duckdb/test/sql/upsert/test_generated_column.test
vendored
Normal file
48
external/duckdb/test/sql/upsert/test_generated_column.test
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
# name: test/sql/upsert/test_generated_column.test
|
||||
# group: [upsert]
|
||||
|
||||
# SET expression targets b (located after the virtual column)
|
||||
|
||||
statement ok
|
||||
CREATE TABLE t1 (
|
||||
a CHAR NOT NULL,
|
||||
c CHAR GENERATED ALWAYS AS (a) VIRTUAL,
|
||||
b INT,
|
||||
);
|
||||
|
||||
statement ok
|
||||
CREATE UNIQUE INDEX t1_idx ON t1 (a);
|
||||
|
||||
statement ok
|
||||
INSERT INTO t1 VALUES ('a', 1) ON CONFLICT(a) DO UPDATE SET b = excluded.b;
|
||||
|
||||
statement ok
|
||||
INSERT INTO t1 VALUES ('a', 1) ON CONFLICT(a) DO UPDATE SET b = excluded.b;
|
||||
|
||||
query III
|
||||
SELECT * FROM t1;
|
||||
----
|
||||
a a 1
|
||||
|
||||
# The ON CONFLICT (a) is logically located after the virtual column
|
||||
|
||||
statement ok
|
||||
CREATE TABLE t2 (
|
||||
b INT,
|
||||
c CHAR GENERATED ALWAYS AS (a) VIRTUAL,
|
||||
a CHAR NOT NULL,
|
||||
);
|
||||
|
||||
statement ok
|
||||
CREATE UNIQUE INDEX t2_idx ON t2 (a);
|
||||
|
||||
statement ok
|
||||
INSERT INTO t2 VALUES (1, 'a') ON CONFLICT(a) DO UPDATE SET b = excluded.b;
|
||||
|
||||
statement ok
|
||||
INSERT INTO t2 VALUES (1, 'a') ON CONFLICT(a) DO UPDATE SET b = excluded.b;
|
||||
|
||||
query III
|
||||
SELECT * FROM t1;
|
||||
----
|
||||
a a 1
|
||||
40
external/duckdb/test/sql/upsert/test_problematic_conditional_do_update.test
vendored
Normal file
40
external/duckdb/test/sql/upsert/test_problematic_conditional_do_update.test
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
# name: test/sql/upsert/test_problematic_conditional_do_update.test
|
||||
# group: [upsert]
|
||||
|
||||
statement ok
|
||||
CREATE TABLE users (
|
||||
id BIGINT PRIMARY KEY,
|
||||
username TEXT UNIQUE,
|
||||
email TEXT
|
||||
);
|
||||
|
||||
# FIXME: not consistent
|
||||
mode skip
|
||||
|
||||
# The condition skips the last tuple
|
||||
statement error
|
||||
INSERT INTO users (id, username, email)
|
||||
VALUES
|
||||
(3, 'inner_conflict', 'test'),
|
||||
(3, 'inner_conflict2', 'other_test'),
|
||||
(3, 'inner_conflict3', 'filtered_out')
|
||||
ON CONFLICT (id) DO
|
||||
UPDATE SET email = EXCLUDED.email
|
||||
WHERE EXCLUDED.email != 'filtered_out'
|
||||
----
|
||||
Not implemented Error: Inner conflicts detected with a conditional DO UPDATE on-conflict action, not fully implemented yet
|
||||
|
||||
# The result of the condition can also be influenced based on previous updates
|
||||
statement error
|
||||
INSERT INTO users (id, username, email)
|
||||
VALUES
|
||||
(3, 'inner_conflict', 'test'),
|
||||
(3, 'inner_conflict2', 'other_test'),
|
||||
(3, 'inner_conflict3', 'yet_another_test'),
|
||||
(3, 'inner_conflict4', 'dont_skip_me')
|
||||
ON CONFLICT (id) DO
|
||||
UPDATE SET email = EXCLUDED.email
|
||||
WHERE email != 'other_test' OR EXCLUDED.email == 'dont_skip_me'
|
||||
RETURNING *;
|
||||
----
|
||||
Not implemented Error: Inner conflicts detected with a conditional DO UPDATE on-conflict action, not fully implemented yet
|
||||
90
external/duckdb/test/sql/upsert/upsert_aliased.test
vendored
Normal file
90
external/duckdb/test/sql/upsert/upsert_aliased.test
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
# name: test/sql/upsert/upsert_aliased.test
|
||||
# group: [upsert]
|
||||
|
||||
statement ok
|
||||
pragma enable_verification;
|
||||
|
||||
statement ok
|
||||
create table tbl (
|
||||
i integer,
|
||||
j integer unique
|
||||
);
|
||||
|
||||
statement ok
|
||||
insert into tbl values (5,3), (6,7);
|
||||
|
||||
# This works when we don't reference it anywhere
|
||||
statement ok
|
||||
insert into tbl AS test values (3,5), (8,3), (2,6) on conflict (j) do update set i = excluded.i * 2 where i <= excluded.i;
|
||||
|
||||
query II
|
||||
select * from tbl order by all
|
||||
----
|
||||
2 6
|
||||
3 5
|
||||
6 7
|
||||
16 3
|
||||
|
||||
# We can use the alias in the expressions
|
||||
statement ok
|
||||
insert into tbl AS test values (2,3) on conflict do update set i = test.i;
|
||||
|
||||
# Essentially a no-op
|
||||
query II
|
||||
select * from tbl order by all
|
||||
----
|
||||
2 6
|
||||
3 5
|
||||
6 7
|
||||
16 3
|
||||
|
||||
# We can use the 'test' alias in the conflict target condition
|
||||
|
||||
query I
|
||||
insert into tbl as test values (2,3) on conflict (j) do update set i = excluded.j where test.i < 5;
|
||||
----
|
||||
0
|
||||
|
||||
statement ok
|
||||
insert into tbl as test values (2,3) on conflict (j) do update set i = excluded.j where test.i >= 5;
|
||||
|
||||
query II rowsort
|
||||
select * from tbl
|
||||
----
|
||||
2 6
|
||||
3 3
|
||||
3 5
|
||||
6 7
|
||||
|
||||
# We can also use the 'test' alias in the DO UPDATE condition
|
||||
|
||||
statement ok
|
||||
insert into tbl as test (j, i) values (5,3) on conflict (j) do update set i = 10 where test.j <= 3;
|
||||
|
||||
# No-op, do update condition was not met
|
||||
query II rowsort
|
||||
select * from tbl;
|
||||
----
|
||||
2 6
|
||||
3 3
|
||||
3 5
|
||||
6 7
|
||||
|
||||
statement ok
|
||||
insert into tbl as test (j, i) values (5,3) on conflict (j) do update set i = 10 where test.j > 3;
|
||||
|
||||
# Now 'i' is changed to 10 in the conflicting tuple
|
||||
query II
|
||||
select * from tbl order by all
|
||||
----
|
||||
2 6
|
||||
3 3
|
||||
6 7
|
||||
10 5
|
||||
|
||||
# When we alias to 'excluded' we create an ambiguity error
|
||||
|
||||
statement error
|
||||
insert into tbl as excluded values (8,3) on conflict (j) do update set i = 5;
|
||||
----
|
||||
Ambiguous reference to table "excluded"
|
||||
218
external/duckdb/test/sql/upsert/upsert_basic.test
vendored
Normal file
218
external/duckdb/test/sql/upsert/upsert_basic.test
vendored
Normal file
@@ -0,0 +1,218 @@
|
||||
# name: test/sql/upsert/upsert_basic.test
|
||||
# group: [upsert]
|
||||
|
||||
statement ok
|
||||
PRAGMA enable_verification;
|
||||
|
||||
statement ok
|
||||
CREATE TABLE tbl(
|
||||
i INT PRIMARY KEY,
|
||||
j INT UNIQUE,
|
||||
k INT
|
||||
);
|
||||
|
||||
statement ok
|
||||
INSERT INTO tbl VALUES (1, 10, 1), (2, 20, 1), (3, 30, 2);
|
||||
|
||||
# Update the on-conflict column.
|
||||
statement ok
|
||||
INSERT INTO tbl VALUES (3, 5, 1)
|
||||
ON CONFLICT (i) DO UPDATE SET i = i + 1;
|
||||
|
||||
query III
|
||||
SELECT i, j, k FROM tbl ORDER BY ALL;
|
||||
----
|
||||
1 10 1
|
||||
2 20 1
|
||||
4 30 2
|
||||
|
||||
query III
|
||||
SELECT i, j, k FROM tbl WHERE i = 4;
|
||||
----
|
||||
4 30 2
|
||||
|
||||
# Update the on-conflict column again.
|
||||
statement ok
|
||||
INSERT INTO tbl VALUES (4, 30, 2)
|
||||
ON CONFLICT (i) DO UPDATE SET i = i - 1;
|
||||
|
||||
query III
|
||||
SELECT i, j, k FROM tbl ORDER BY ALL;
|
||||
----
|
||||
1 10 1
|
||||
2 20 1
|
||||
3 30 2
|
||||
|
||||
# Cannot update to the same PK value as another column.
|
||||
statement error
|
||||
INSERT INTO tbl VALUES (3, 30, 2)
|
||||
ON CONFLICT (i) DO UPDATE SET i = i - 2;
|
||||
----
|
||||
<REGEX>:Constraint Error.*violates primary key constraint.*
|
||||
|
||||
# 'excluded' refers to the VALUES list, turning this into:
|
||||
# (k)2 + (k.excluded)1 = 3
|
||||
statement ok
|
||||
insert into tbl VALUES
|
||||
(3,5,1)
|
||||
ON CONFLICT (i) DO UPDATE SET k = k + excluded.k;
|
||||
|
||||
query III
|
||||
select * from tbl;
|
||||
----
|
||||
1 10 1
|
||||
2 20 1
|
||||
3 30 3
|
||||
|
||||
# The ON CONFLICT does not refer to a column that's indexed on, so it's never true
|
||||
statement error
|
||||
insert into tbl VALUES
|
||||
(3,5,1)
|
||||
ON CONFLICT (k) DO UPDATE SET k = excluded.k;
|
||||
----
|
||||
Binder Error: The specified columns as conflict target are not referenced by a UNIQUE/PRIMARY KEY CONSTRAINT
|
||||
|
||||
# Overwrite the existing value with the new value
|
||||
statement ok
|
||||
insert into tbl VALUES
|
||||
(3,5,1)
|
||||
ON CONFLICT (i) DO UPDATE SET k = excluded.k;
|
||||
|
||||
query III
|
||||
select * from tbl;
|
||||
----
|
||||
1 10 1
|
||||
2 20 1
|
||||
3 30 1
|
||||
|
||||
# Don't alter the existing row, but still insert the non-conflicting row
|
||||
statement ok
|
||||
insert into tbl VALUES
|
||||
(4,2,3),
|
||||
(3,5,10)
|
||||
ON CONFLICT (i) DO NOTHING;
|
||||
|
||||
query III
|
||||
select * from tbl;
|
||||
----
|
||||
1 10 1
|
||||
2 20 1
|
||||
3 30 1
|
||||
4 2 3
|
||||
|
||||
# Two rows cause a conflict, on the same existing row
|
||||
# only the last one is used
|
||||
statement ok
|
||||
insert into tbl VALUES
|
||||
(3,3,10),
|
||||
(3,3,10)
|
||||
ON CONFLICT (i) DO UPDATE SET
|
||||
k = excluded.k;
|
||||
|
||||
query III
|
||||
select * from tbl order by all
|
||||
----
|
||||
1 10 1
|
||||
2 20 1
|
||||
3 30 10
|
||||
4 2 3
|
||||
|
||||
# condition is not matched - no updates have happened
|
||||
query I
|
||||
insert into tbl VALUES (3,5,1) ON CONFLICT (i) DO UPDATE SET k = 1 WHERE k < 5;
|
||||
----
|
||||
0
|
||||
|
||||
query III
|
||||
select * from tbl;
|
||||
----
|
||||
1 10 1
|
||||
2 20 1
|
||||
3 30 10
|
||||
4 2 3
|
||||
|
||||
# When the condition is met, the DO is performed
|
||||
query I
|
||||
insert into tbl VALUES (3,5,1) ON CONFLICT (i) DO UPDATE SET k = 1 WHERE k >= 5;
|
||||
----
|
||||
1
|
||||
|
||||
# 'k' in row_id:3 is updated to 1
|
||||
query III
|
||||
select * from tbl;
|
||||
----
|
||||
1 10 1
|
||||
2 20 1
|
||||
3 30 1
|
||||
4 2 3
|
||||
|
||||
# When the condition is on the DO UPDATE part,
|
||||
# it will always succeed, but turn into a DO NOTHING for the conflicts that don't meet the condition
|
||||
|
||||
statement ok
|
||||
insert into tbl VALUES (3,5,3) on conflict (i) do update set k = 10 WHERE k != 1;
|
||||
|
||||
# Unchanged, because the where clause is not met
|
||||
query III
|
||||
select * from tbl;
|
||||
----
|
||||
1 10 1
|
||||
2 20 1
|
||||
3 30 1
|
||||
4 2 3
|
||||
|
||||
statement ok
|
||||
insert into tbl VALUES (3,5,3) on conflict (i) do update set k = 10 WHERE k == 1;
|
||||
|
||||
# Changed, because the where clause is met
|
||||
query III
|
||||
select * from tbl;
|
||||
----
|
||||
1 10 1
|
||||
2 20 1
|
||||
3 30 10
|
||||
4 2 3
|
||||
|
||||
# When we don't specify a conflict target, all unique/primary key constraints are used as the conflict target
|
||||
statement ok
|
||||
insert into tbl VALUES (5,1,0), (3,5,20) ON CONFLICT DO NOTHING;
|
||||
|
||||
query III
|
||||
select * from tbl;
|
||||
----
|
||||
1 10 1
|
||||
2 20 1
|
||||
3 30 10
|
||||
4 2 3
|
||||
5 1 0
|
||||
|
||||
# Not supported because:
|
||||
# > It's because one insert row could violate multiple different unique constraints,
|
||||
# with it being a different row for each of the constraints that's causing the violation,
|
||||
# and the upsert is only intended to update a single row.
|
||||
# https://sqlite.org/forum/info/45cf84d3e89d590d
|
||||
statement error
|
||||
insert into tbl VALUES (5,1,0), (3,5,20) ON CONFLICT DO UPDATE set k = excluded.k;
|
||||
----
|
||||
Binder Error: Conflict target has to be provided for a DO UPDATE operation when the table has multiple UNIQUE/PRIMARY KEY constraints
|
||||
|
||||
statement ok
|
||||
create or replace table single_constraint (
|
||||
i integer PRIMARY KEY,
|
||||
j integer,
|
||||
k varchar,
|
||||
);
|
||||
|
||||
statement ok
|
||||
insert into single_constraint values (5,1,'hello'), (1,10,'test');
|
||||
|
||||
# This is however accepted if only a single constraint exists on the table
|
||||
statement ok
|
||||
insert into single_constraint values (1,5,'bye'), (3,10,'quack') on conflict do update set j = excluded.j, k = concat(k, excluded.k);
|
||||
|
||||
query III
|
||||
select * from single_constraint
|
||||
----
|
||||
5 1 hello
|
||||
1 5 testbye
|
||||
3 10 quack
|
||||
40
external/duckdb/test/sql/upsert/upsert_conflict_target.test
vendored
Normal file
40
external/duckdb/test/sql/upsert/upsert_conflict_target.test
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
# name: test/sql/upsert/upsert_conflict_target.test
|
||||
# group: [upsert]
|
||||
|
||||
statement ok
|
||||
PRAGMA enable_verification;
|
||||
|
||||
statement ok
|
||||
CREATE OR REPLACE TABLE tbl (a INT, b INT, c INT, PRIMARY KEY (a, b));
|
||||
|
||||
# a and b combined are not unique.
|
||||
statement error
|
||||
INSERT INTO tbl VALUES (1, 2, 3), (1, 2, 3);
|
||||
----
|
||||
Constraint Error: PRIMARY KEY or UNIQUE constraint violation: duplicate key
|
||||
|
||||
statement ok
|
||||
INSERT INTO tbl VALUES (1, 2, 3), (1, 4, 5);
|
||||
|
||||
# Conflict target does not match any index on the table, only valid conflict target would be: (a,b)
|
||||
statement error
|
||||
INSERT INTO tbl VALUES (1,4,7), (1,8,4) ON CONFLICT (a) DO UPDATE SET c = 5;
|
||||
----
|
||||
Binder Error: The specified columns as conflict target are not referenced by a UNIQUE/PRIMARY KEY CONSTRAINT
|
||||
|
||||
# Conflict target does not match any index on the table, only valid conflict target would be: (a,b)
|
||||
statement error
|
||||
INSERT INTO tbl VALUES (1,4,7), (1,8,4) ON CONFLICT (b) DO UPDATE SET c = 5;
|
||||
----
|
||||
Binder Error: The specified columns as conflict target are not referenced by a UNIQUE/PRIMARY KEY CONSTRAINT
|
||||
|
||||
# Conflict target matches the index on the table, conflict is resolved by the ON CONFLICT clause
|
||||
statement ok
|
||||
INSERT INTO tbl VALUES (1,4,7), (1,8,4) ON CONFLICT (a,b) DO UPDATE SET c = 5;
|
||||
|
||||
query III
|
||||
SELECT a, b, c FROM tbl ORDER BY ALL;
|
||||
----
|
||||
1 2 3
|
||||
1 4 5
|
||||
1 8 4
|
||||
33
external/duckdb/test/sql/upsert/upsert_conflict_target_index.test
vendored
Normal file
33
external/duckdb/test/sql/upsert/upsert_conflict_target_index.test
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
# name: test/sql/upsert/upsert_conflict_target_index.test
|
||||
# group: [upsert]
|
||||
|
||||
statement ok
|
||||
pragma enable_verification;
|
||||
|
||||
statement ok
|
||||
create or replace table index_tbl (
|
||||
i integer,
|
||||
j integer
|
||||
);
|
||||
|
||||
statement ok
|
||||
insert into index_tbl values (5, 3);
|
||||
|
||||
statement ok
|
||||
create unique index other_index on index_tbl(i);
|
||||
|
||||
statement error
|
||||
insert into index_tbl values (5, 5);
|
||||
----
|
||||
|
||||
query II
|
||||
select * from index_tbl;
|
||||
----
|
||||
5 3
|
||||
|
||||
# TODO: Indexes are only checked as part of committing a transaction, not in the Insert, so we currently can't support the
|
||||
# ON CONFLICT ON CONSTRAINT <constraint_name> syntax
|
||||
statement error
|
||||
insert into index_tbl values (5, 10) on conflict on constraint other_index do update set j = excluded.j;
|
||||
----
|
||||
Not implemented Error: ON CONSTRAINT conflict target is not supported yet
|
||||
36
external/duckdb/test/sql/upsert/upsert_coverage.test
vendored
Normal file
36
external/duckdb/test/sql/upsert/upsert_coverage.test
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
# name: test/sql/upsert/upsert_coverage.test
|
||||
# group: [upsert]
|
||||
|
||||
statement ok
|
||||
PRAGMA enable_verification;
|
||||
|
||||
statement ok
|
||||
CREATE TABLE tbl (a INT, b INT UNIQUE, c INT UNIQUE, d INT UNIQUE);
|
||||
|
||||
statement ok
|
||||
INSERT INTO tbl (b, c, d) VALUES (1, 2, 3), (2, 3, 1), (3, 1, 2)
|
||||
|
||||
# Create conflicts in three existing tuples with one INSERT tuple.
|
||||
# Each conflict has a different row ID.
|
||||
|
||||
# We never have to deal with one-to-many conflicts in anything other than
|
||||
# a DO NOTHING action. That is because we need a conflict target
|
||||
# to use any sort of WHERE or SET expression that references the existing table.
|
||||
|
||||
statement ok
|
||||
INSERT INTO tbl(b, c, d) VALUES (3, 3, 3) ON CONFLICT DO NOTHING;
|
||||
|
||||
query III
|
||||
SELECT b, c, d FROM tbl ORDER BY ALL;
|
||||
----
|
||||
1 2 3
|
||||
2 3 1
|
||||
3 1 2
|
||||
|
||||
# We fail without a conflict target.
|
||||
|
||||
statement error
|
||||
INSERT INTO tbl(b, c, d) VALUES (3, 3, 3)
|
||||
ON CONFLICT DO UPDATE SET b = EXCLUDED.b, c = EXCLUDED.c, d = EXCLUDED.d;
|
||||
----
|
||||
<REGEX>:Binder Error.*Conflict target has to be provided for a DO UPDATE operation when the table has multiple UNIQUE/PRIMARY KEY constraints.*
|
||||
47
external/duckdb/test/sql/upsert/upsert_default.test
vendored
Normal file
47
external/duckdb/test/sql/upsert/upsert_default.test
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
# name: test/sql/upsert/upsert_default.test
|
||||
# group: [upsert]
|
||||
|
||||
statement ok
|
||||
pragma enable_verification;
|
||||
|
||||
statement ok
|
||||
create table tbl (
|
||||
a integer DEFAULT 5,
|
||||
b integer unique,
|
||||
c integer DEFAULT 10
|
||||
);
|
||||
|
||||
statement ok
|
||||
insert into tbl(b) VALUES (3), (5), (6);
|
||||
|
||||
statement ok
|
||||
insert into tbl(b) VALUES (7), (3), (4) ON CONFLICT do update set c = 5, a = 10;
|
||||
|
||||
query III rowsort
|
||||
select * from tbl;
|
||||
----
|
||||
10 3 5
|
||||
5 4 10
|
||||
5 5 10
|
||||
5 6 10
|
||||
5 7 10
|
||||
|
||||
statement ok
|
||||
create table t (i int primary key, j int);
|
||||
|
||||
query I
|
||||
insert into t values (1, 1) on conflict do nothing;
|
||||
----
|
||||
1
|
||||
|
||||
# 0 updates/insertions were performed
|
||||
query I
|
||||
insert into t values (1, 1) on conflict do nothing
|
||||
----
|
||||
0
|
||||
|
||||
# 0 insertions, but one tuple is updated
|
||||
query I
|
||||
insert into t values (1, 1) on conflict (i) do update set j = excluded.i;
|
||||
----
|
||||
1
|
||||
42
external/duckdb/test/sql/upsert/upsert_default_expressions.test
vendored
Normal file
42
external/duckdb/test/sql/upsert/upsert_default_expressions.test
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
# name: test/sql/upsert/upsert_default_expressions.test
|
||||
# group: [upsert]
|
||||
|
||||
statement ok
|
||||
pragma enable_verification;
|
||||
|
||||
statement ok
|
||||
create or replace table tbl (
|
||||
a integer primary key default 4,
|
||||
b integer DEFAULT 3
|
||||
);
|
||||
|
||||
statement ok
|
||||
insert into tbl VALUES (2,3), (4,5)
|
||||
|
||||
query II
|
||||
select * from tbl;
|
||||
----
|
||||
2 3
|
||||
4 5
|
||||
|
||||
# DEFAULT in set expression
|
||||
statement ok
|
||||
insert into tbl VALUES (DEFAULT, 6) ON CONFLICT (a) DO UPDATE SET b = DEFAULT
|
||||
|
||||
query II
|
||||
select * from tbl;
|
||||
----
|
||||
2 3
|
||||
4 3
|
||||
|
||||
# DEFAULT in ON CONFLICT (..) WHERE <expr>
|
||||
statement error
|
||||
insert into tbl VALUES (4,8) ON CONFLICT (a) DO UPDATE SET b = excluded.b WHERE a = DEFAULT;
|
||||
----
|
||||
WHERE clause cannot contain DEFAULT clause
|
||||
|
||||
# DEFAULT in DO UPDATE SET .. WHERE <expr>
|
||||
statement error
|
||||
insert into tbl VALUES (4,3) ON CONFLICT (a) DO UPDATE SET b = excluded.b WHERE excluded.b = DEFAULT * 2;
|
||||
----
|
||||
WHERE clause cannot contain DEFAULT clause
|
||||
44
external/duckdb/test/sql/upsert/upsert_default_value_causes_conflict.test
vendored
Normal file
44
external/duckdb/test/sql/upsert/upsert_default_value_causes_conflict.test
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
# name: test/sql/upsert/upsert_default_value_causes_conflict.test
|
||||
# group: [upsert]
|
||||
|
||||
statement ok
|
||||
pragma enable_verification;
|
||||
|
||||
statement ok
|
||||
create or replace table tbl (
|
||||
a integer primary key default 5,
|
||||
b integer
|
||||
);
|
||||
|
||||
statement ok
|
||||
insert into tbl(b) VALUES (10);
|
||||
|
||||
query II
|
||||
select * from tbl;
|
||||
----
|
||||
5 10
|
||||
|
||||
# The default expression is a constant, can't be inserted twice
|
||||
statement error
|
||||
insert into tbl(b) VALUES (10);
|
||||
----
|
||||
Constraint Error: Duplicate key "a: 5" violates primary key constraint
|
||||
|
||||
# We can ignore the error
|
||||
statement ok
|
||||
insert into tbl(b) VALUES (10) ON CONFLICT (a) DO NOTHING;
|
||||
|
||||
# The tuple is not inserted
|
||||
query II
|
||||
select * from tbl;
|
||||
----
|
||||
5 10
|
||||
|
||||
# We can also change the value of 'b', but not of 'a' because it's indexed on
|
||||
statement ok
|
||||
insert into tbl(b) VALUES (10) ON CONFLICT (a) DO UPDATE SET b = excluded.b * 2;
|
||||
|
||||
query II
|
||||
select * from tbl;
|
||||
----
|
||||
5 20
|
||||
20
external/duckdb/test/sql/upsert/upsert_default_values.test
vendored
Normal file
20
external/duckdb/test/sql/upsert/upsert_default_values.test
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
# name: test/sql/upsert/upsert_default_values.test
|
||||
# group: [upsert]
|
||||
|
||||
statement ok
|
||||
pragma enable_verification;
|
||||
|
||||
statement ok
|
||||
create or replace table tbl (
|
||||
a integer primary key DEFAULT 5,
|
||||
b integer
|
||||
);
|
||||
|
||||
statement ok
|
||||
insert into tbl DEFAULT VALUES;
|
||||
|
||||
query II
|
||||
FROM tbl
|
||||
----
|
||||
5 NULL
|
||||
|
||||
51
external/duckdb/test/sql/upsert/upsert_distinct_bug.test
vendored
Normal file
51
external/duckdb/test/sql/upsert/upsert_distinct_bug.test
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
# name: test/sql/upsert/upsert_distinct_bug.test
|
||||
# group: [upsert]
|
||||
|
||||
# Create raw data table
|
||||
statement ok
|
||||
CREATE TABLE test_table_raw(id VARCHAR, name VARCHAR);
|
||||
|
||||
# Insert raw data
|
||||
statement ok
|
||||
INSERT INTO test_table_raw VALUES
|
||||
('abc001','foo'),
|
||||
('abc002','bar'),
|
||||
('abc001','foo2'),
|
||||
('abc002','bar2');
|
||||
|
||||
# Create aggregated data table
|
||||
statement ok
|
||||
CREATE TABLE test_table(id VARCHAR PRIMARY KEY, name VARCHAR);
|
||||
|
||||
|
||||
# Insert aggregated data
|
||||
statement error
|
||||
INSERT INTO test_table
|
||||
SELECT
|
||||
DISTINCT(id) as id,
|
||||
name
|
||||
FROM test_table_raw;
|
||||
----
|
||||
|
||||
# Insert aggregated data
|
||||
statement error
|
||||
INSERT INTO test_table
|
||||
SELECT
|
||||
DISTINCT(id) as id,
|
||||
name
|
||||
FROM test_table_raw;
|
||||
----
|
||||
|
||||
# Insert aggregated data second time with "INSERT OR IGNORE" => Segmentation fault
|
||||
# This contains conflicts between the to-be-inserted rows, still won't succeed
|
||||
# FIXME - this sometimes works - it depends on how the aggregate returns rows
|
||||
statement maybe
|
||||
INSERT OR IGNORE INTO test_table
|
||||
SELECT
|
||||
DISTINCT(id) as id,
|
||||
name
|
||||
FROM test_table_raw;
|
||||
----
|
||||
|
||||
statement ok
|
||||
SELECT * FROM test_table_raw;
|
||||
17
external/duckdb/test/sql/upsert/upsert_duplicates_issue.test
vendored
Normal file
17
external/duckdb/test/sql/upsert/upsert_duplicates_issue.test
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
# name: test/sql/upsert/upsert_duplicates_issue.test
|
||||
# group: [upsert]
|
||||
|
||||
statement ok
|
||||
pragma enable_verification;
|
||||
|
||||
require parquet
|
||||
|
||||
statement ok
|
||||
CREATE TABLE tmp_edges(from_v VARCHAR, to_v VARCHAR, PRIMARY KEY(from_v, to_v));
|
||||
|
||||
statement ok
|
||||
INSERT INTO tmp_edges
|
||||
from 'data/parquet-testing/upsert_bug.parquet'
|
||||
ON CONFLICT DO UPDATE SET
|
||||
from_v = excluded.from_v
|
||||
;
|
||||
74
external/duckdb/test/sql/upsert/upsert_excluded_references.test
vendored
Normal file
74
external/duckdb/test/sql/upsert/upsert_excluded_references.test
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
# name: test/sql/upsert/upsert_excluded_references.test
|
||||
# group: [upsert]
|
||||
|
||||
statement ok
|
||||
pragma enable_verification;
|
||||
|
||||
# Within the ON CONFLICT clause, we can have special column references that are qualified with 'excluded'
|
||||
# These refer to the to-be-inserted tuples that caused the conflict, instead of the existing tuples that were found by the conflict.
|
||||
|
||||
statement ok
|
||||
create or replace table tbl (
|
||||
a integer primary key,
|
||||
b integer
|
||||
);
|
||||
|
||||
statement ok
|
||||
insert into tbl VALUES (1,2), (2,2);
|
||||
|
||||
query II
|
||||
select * from tbl;
|
||||
----
|
||||
1 2
|
||||
2 2
|
||||
|
||||
# Conflict on '1' in 'a'
|
||||
statement error
|
||||
insert into tbl VALUES (1,3), (3,4);
|
||||
----
|
||||
Constraint Error: Duplicate key "a: 1" violates primary key constraint
|
||||
|
||||
# Usage of 'excluded' in a SET expression
|
||||
statement ok
|
||||
insert into tbl VALUES (1,3), (3,4) ON CONFLICT (a) DO UPDATE SET b = excluded.b;
|
||||
|
||||
query II
|
||||
select * from tbl;
|
||||
----
|
||||
1 3
|
||||
2 2
|
||||
3 4
|
||||
|
||||
# Usage of 'excluded' in a ON CONFLICT (..) WHERE <expr>
|
||||
statement error
|
||||
insert into tbl VALUES (4,3), (3,8) ON CONFLICT (a) WHERE excluded.b < 8 DO NOTHING;
|
||||
----
|
||||
ON CONFLICT WHERE clause is only supported in DO UPDATE SET
|
||||
|
||||
statement ok
|
||||
insert into tbl VALUES (4,3), (3,8) ON CONFLICT (a) DO UPDATE SET b = 10;
|
||||
|
||||
query II
|
||||
select * from tbl;
|
||||
----
|
||||
1 3
|
||||
2 2
|
||||
3 10
|
||||
4 3
|
||||
|
||||
# Usage of 'excluded' in a DO UPDATE SET ... WHERE <expr>
|
||||
|
||||
# Both '2' and '3' are conflicts, but only '2' meets the condition
|
||||
# When the condition is not met, this turns into a DO NOTHING instead for that tuple
|
||||
statement ok
|
||||
insert into tbl VALUES (3,8), (2,2), (7,2) ON CONFLICT (a) DO UPDATE SET b = b*2 WHERE b == excluded.b;
|
||||
|
||||
# Only '2' is updated
|
||||
query II
|
||||
select * from tbl;
|
||||
----
|
||||
1 3
|
||||
2 4
|
||||
3 10
|
||||
4 3
|
||||
7 2
|
||||
50
external/duckdb/test/sql/upsert/upsert_explicit_index.test
vendored
Normal file
50
external/duckdb/test/sql/upsert/upsert_explicit_index.test
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
# name: test/sql/upsert/upsert_explicit_index.test
|
||||
# description: Test index UPSERTs.
|
||||
# group: [upsert]
|
||||
|
||||
statement ok
|
||||
pragma enable_verification;
|
||||
|
||||
statement ok
|
||||
CREATE TABLE tbl (i INT, j INT);
|
||||
|
||||
statement ok
|
||||
INSERT INTO tbl VALUES (5, 3), (3, 2);
|
||||
|
||||
statement ok
|
||||
CREATE UNIQUE INDEX my_index ON tbl(i);
|
||||
|
||||
statement ok
|
||||
INSERT INTO tbl VALUES (5, 2) ON CONFLICT (i) DO UPDATE SET j = 10;
|
||||
|
||||
query II
|
||||
SELECT i, j FROM tbl ORDER BY ALL DESC;
|
||||
----
|
||||
5 10
|
||||
3 2
|
||||
|
||||
statement ok
|
||||
DROP TABLE tbl CASCADE;
|
||||
|
||||
statement ok
|
||||
CREATE TABLE tbl (i INT PRIMARY KEY, j INT);
|
||||
|
||||
statement ok
|
||||
INSERT INTO tbl VALUES (42, 21), (21, 42);
|
||||
|
||||
statement ok
|
||||
CREATE INDEX my_index ON tbl(j);
|
||||
|
||||
statement ok
|
||||
INSERT INTO tbl VALUES (42, 20) ON CONFLICT DO UPDATE SET j = 30;
|
||||
|
||||
query III
|
||||
SELECT i, j, rowid FROM tbl WHERE j = 30;
|
||||
----
|
||||
42 30 2
|
||||
|
||||
query III
|
||||
SELECT i, j, rowid FROM tbl ORDER BY ALL;
|
||||
----
|
||||
21 42 1
|
||||
42 30 2
|
||||
57
external/duckdb/test/sql/upsert/upsert_global_mixed_conflicts.test
vendored
Normal file
57
external/duckdb/test/sql/upsert/upsert_global_mixed_conflicts.test
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
# name: test/sql/upsert/upsert_global_mixed_conflicts.test
|
||||
# group: [upsert]
|
||||
|
||||
statement ok
|
||||
create table tbl (
|
||||
number INTEGER PRIMARY KEY,
|
||||
str VARCHAR
|
||||
);
|
||||
|
||||
statement ok
|
||||
insert into tbl VALUES
|
||||
(1, 'd'),
|
||||
(3, 'nope'),
|
||||
(2, 'n')
|
||||
;
|
||||
|
||||
## Postgres says:
|
||||
## ERROR: ON CONFLICT DO UPDATE command cannot affect row a second time
|
||||
## HINT: Ensure that no rows proposed for insertion within the same command have duplicate constrained values.
|
||||
# This insert causes both:
|
||||
# - conflicts only within the to-be-inserted-data
|
||||
# - conflicts only with the existing data
|
||||
# - both conflicts with the existing data as well as within the to-be-inserted-data
|
||||
statement ok
|
||||
insert into tbl VALUES
|
||||
(1, 'c'), -- conflict (existing)
|
||||
(6, 'yep'),
|
||||
(3, 'abc'), -- conflict (existing)
|
||||
(4, 'abc'),
|
||||
(7, 'tes'),
|
||||
(2, 'b'), -- conflict (existing)
|
||||
(1, 'c'), -- conflict (existing + inner)
|
||||
(5, 'abc'),
|
||||
(7, 'tes'), -- conflict (inner)
|
||||
(2, 'b') -- conflict (existing + inner)
|
||||
ON CONFLICT (number) DO UPDATE SET str = excluded.str || 'e';
|
||||
|
||||
|
||||
query II rowsort
|
||||
select * from tbl;
|
||||
----
|
||||
1 ce
|
||||
2 be
|
||||
3 abce
|
||||
4 abc
|
||||
5 abc
|
||||
6 yep
|
||||
7 tes
|
||||
|
||||
## sqlite says this is the correct order ??:
|
||||
## 1 e
|
||||
## 2 e
|
||||
## 3 e
|
||||
## 4 abc
|
||||
## 5 abc
|
||||
## 6 yep
|
||||
## 7 e
|
||||
20
external/duckdb/test/sql/upsert/upsert_inner_conflict_do_nothing.test
vendored
Normal file
20
external/duckdb/test/sql/upsert/upsert_inner_conflict_do_nothing.test
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
# name: test/sql/upsert/upsert_inner_conflict_do_nothing.test
|
||||
# group: [upsert]
|
||||
|
||||
statement ok
|
||||
create table tbl(
|
||||
i int primary key
|
||||
);
|
||||
|
||||
statement ok
|
||||
insert into tbl values (1);
|
||||
|
||||
# The inserted data has a conflict within the to-be-inserted-data (inner conflict)
|
||||
# As well as a conflict with the existing data
|
||||
statement ok
|
||||
insert into tbl select 1 from range(2) on conflict do nothing;
|
||||
|
||||
query I
|
||||
select * from tbl;
|
||||
----
|
||||
1
|
||||
91
external/duckdb/test/sql/upsert/upsert_lambda.test
vendored
Normal file
91
external/duckdb/test/sql/upsert/upsert_lambda.test
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
# name: test/sql/upsert/upsert_lambda.test
|
||||
# group: [upsert]
|
||||
|
||||
statement ok
|
||||
PRAGMA enable_verification;
|
||||
|
||||
statement ok
|
||||
CREATE OR REPLACE TABLE foo (
|
||||
pk_col INT PRIMARY KEY,
|
||||
str VARCHAR,
|
||||
str_list VARCHAR[],
|
||||
payload_col INT
|
||||
);
|
||||
|
||||
statement ok
|
||||
INSERT INTO foo
|
||||
SELECT 1, 'hello', ['x', 'y', 'z'], 40
|
||||
ON CONFLICT DO UPDATE SET
|
||||
str = list_reduce(EXCLUDED.str_list, lambda x, y: x || '||' || y);
|
||||
|
||||
query IIII
|
||||
FROM foo;
|
||||
----
|
||||
1 hello [x, y, z] 40
|
||||
|
||||
# Use the new (excluded) list as input.
|
||||
|
||||
statement ok
|
||||
INSERT INTO foo
|
||||
SELECT 1, 'world', ['a', 'b', 'c'], 41
|
||||
ON CONFLICT DO UPDATE SET
|
||||
str = list_reduce(EXCLUDED.str_list, lambda x, y: x || '||' || y);
|
||||
|
||||
query IIII
|
||||
FROM foo;
|
||||
----
|
||||
1 a||b||c [x, y, z] 40
|
||||
|
||||
# Additionally update the payload.
|
||||
|
||||
statement ok
|
||||
INSERT INTO foo
|
||||
SELECT 1, '', ['1', '2'], 42
|
||||
ON CONFLICT DO UPDATE SET
|
||||
str = list_reduce(EXCLUDED.str_list, lambda x, y: x || '||' || y),
|
||||
payload_col = EXCLUDED.payload_col;
|
||||
|
||||
query IIII
|
||||
FROM foo;
|
||||
----
|
||||
1 1||2 [x, y, z] 42
|
||||
|
||||
# Use the existing list as input.
|
||||
|
||||
statement ok
|
||||
INSERT INTO foo
|
||||
SELECT 1, '', ['l', 'm', 'n'], 43
|
||||
ON CONFLICT DO UPDATE SET
|
||||
str = list_reduce(str_list, lambda x, y: x || '||' || y);
|
||||
|
||||
query IIII
|
||||
FROM foo;
|
||||
----
|
||||
1 x||y||z [x, y, z] 42
|
||||
|
||||
# Reference the existing and the new (excluded) str column without qualification.
|
||||
|
||||
statement ok
|
||||
INSERT INTO foo
|
||||
SELECT 1, 'world', ['s', 't'], 42
|
||||
ON CONFLICT DO UPDATE SET
|
||||
str = list_reduce(EXCLUDED.str_list, lambda x, y: x || str || y || EXCLUDED.str);
|
||||
|
||||
query IIII
|
||||
FROM foo;
|
||||
----
|
||||
1 sx||y||ztworld [x, y, z] 42
|
||||
|
||||
# lambda function in the WHERE clause.
|
||||
|
||||
statement ok
|
||||
INSERT INTO foo
|
||||
SELECT 1, 'motorcycle', ['brrr', 'brrrrrr'], 1042
|
||||
ON CONFLICT DO UPDATE SET
|
||||
str = 'black-bellied whistling duck'
|
||||
WHERE list_reduce(EXCLUDED.str_list, lambda x, y: x || str || y || EXCLUDED.str) = 'brrrsx||y||ztworldbrrrrrrmotorcycle';
|
||||
|
||||
query IIII
|
||||
FROM foo;
|
||||
----
|
||||
1 black-bellied whistling duck [x, y, z] 42
|
||||
58
external/duckdb/test/sql/upsert/upsert_local_no_tuples.test
vendored
Normal file
58
external/duckdb/test/sql/upsert/upsert_local_no_tuples.test
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
# name: test/sql/upsert/upsert_local_no_tuples.test
|
||||
# group: [upsert]
|
||||
|
||||
statement ok
|
||||
pragma enable_verification;
|
||||
|
||||
# Table with a constraint
|
||||
statement ok
|
||||
create table tbl (
|
||||
a short primary key,
|
||||
b short
|
||||
);
|
||||
|
||||
# Populate the table
|
||||
statement ok
|
||||
insert into tbl(a, b) values(1, 2);
|
||||
|
||||
# Start a transaction, local storage will be created if an INSERT happens
|
||||
statement ok
|
||||
begin transaction;
|
||||
|
||||
# Create a local storage, appending 0 tuples because of DO NOTHING
|
||||
statement ok
|
||||
insert into tbl(a, b) values(1, 2) on conflict do nothing;
|
||||
|
||||
# Scan from the table, hitting the local storage
|
||||
query II
|
||||
select * from tbl where a = 1;
|
||||
----
|
||||
1 2
|
||||
|
||||
# Do it again to test proper cleanup of state
|
||||
statement ok
|
||||
insert into tbl(a, b) values(1, 2) on conflict do nothing;
|
||||
|
||||
# Scan from the table, hitting the local storage
|
||||
statement ok
|
||||
select * from tbl where a = 1;
|
||||
|
||||
statement ok
|
||||
commit;
|
||||
|
||||
statement ok
|
||||
begin transaction;
|
||||
|
||||
# Now create a LocalStorage with tuples before doing an append with 0 tuples
|
||||
statement ok
|
||||
insert into tbl (a, b) values (5,4);
|
||||
|
||||
statement ok
|
||||
insert into tbl(a, b) values(1, 2) on conflict do nothing;
|
||||
|
||||
# Scan from the table, hitting the local storage
|
||||
query II
|
||||
select * from tbl order by a;
|
||||
----
|
||||
1 2
|
||||
5 4
|
||||
16
external/duckdb/test/sql/upsert/upsert_multiple_constraints.test
vendored
Normal file
16
external/duckdb/test/sql/upsert/upsert_multiple_constraints.test
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
# name: test/sql/upsert/upsert_multiple_constraints.test
|
||||
# description: Test upsert with a mix of primary / unique constraints
|
||||
# group: [upsert]
|
||||
|
||||
statement ok
|
||||
CREATE TABLE IF NOT EXISTS tbl (id INTEGER PRIMARY KEY, uniq INTEGER, UNIQUE(uniq));
|
||||
|
||||
query I
|
||||
INSERT OR IGNORE INTO tbl VALUES (1, 1), (2, 1);
|
||||
----
|
||||
1
|
||||
|
||||
query I
|
||||
SELECT uniq FROM tbl
|
||||
----
|
||||
1
|
||||
62
external/duckdb/test/sql/upsert/upsert_order_coverage.test
vendored
Normal file
62
external/duckdb/test/sql/upsert/upsert_order_coverage.test
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
# name: test/sql/upsert/upsert_order_coverage.test
|
||||
# group: [upsert]
|
||||
|
||||
statement ok
|
||||
pragma enable_verification;
|
||||
|
||||
# Create a table, most columns are indexed on
|
||||
statement ok
|
||||
create or replace table tbl(
|
||||
i integer UNIQUE,
|
||||
j integer,
|
||||
k integer PRIMARY KEY
|
||||
);
|
||||
|
||||
statement ok
|
||||
insert into tbl values (3,4,2), (5,3,1);
|
||||
|
||||
query III
|
||||
select * from tbl;
|
||||
----
|
||||
3 4 2
|
||||
5 3 1
|
||||
|
||||
# 'k' is violated in row1 and row2, 'i' is violated in row1
|
||||
# Since our conflict target is on 'k', and the violations of 'i' are a subset of the violations of 'k'
|
||||
# We accept this, and don't throw an error
|
||||
statement ok
|
||||
insert into tbl(k, i) values (2,3), (4,4), (1,8) on conflict (k) do update set j = excluded.j;
|
||||
|
||||
query III
|
||||
select * from tbl;
|
||||
----
|
||||
3 NULL 2
|
||||
5 NULL 1
|
||||
4 NULL 4
|
||||
|
||||
# If this is the other way around, and the violations caused by indexes that are not our conflict target ('i')
|
||||
# are not a subset of the violations caused by the index that is our conflict target ('k') then this is an error
|
||||
# 'i' is violated in row1 and row2, 'k' is only violated in row1
|
||||
statement error
|
||||
insert into tbl(i,k) values (3,2), (5,5) on conflict (k) do update set j = 10;
|
||||
----
|
||||
|
||||
query III
|
||||
select * from tbl;
|
||||
----
|
||||
3 NULL 2
|
||||
5 NULL 1
|
||||
4 NULL 4
|
||||
|
||||
# Only when the non-conflict-target violation shares an insert tuple with a conflict-target violation
|
||||
# Do we not throw on it, so this does cause an error, because the conflict of 'k' is not on the same insert tuple as the conflict of 'k'
|
||||
statement error
|
||||
insert into tbl(i,k) values (3,10), (6,2) on conflict(i) do update set j = 10;
|
||||
----
|
||||
|
||||
query III
|
||||
select * from tbl;
|
||||
----
|
||||
3 NULL 2
|
||||
5 NULL 1
|
||||
4 NULL 4
|
||||
22
external/duckdb/test/sql/upsert/upsert_partial_update.test
vendored
Normal file
22
external/duckdb/test/sql/upsert/upsert_partial_update.test
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
# name: test/sql/upsert/upsert_partial_update.test
|
||||
# group: [upsert]
|
||||
|
||||
statement ok
|
||||
pragma enable_verification;
|
||||
|
||||
statement ok
|
||||
create or replace table tbl (a integer primary key, b integer);
|
||||
|
||||
statement ok
|
||||
insert into tbl VALUES (1,3), (2,2), (3,10), (4,3);
|
||||
|
||||
statement ok
|
||||
insert into tbl VALUES (3,8), (2,2) ON CONFLICT (a) DO UPDATE SET b = b*2 WHERE b == excluded.b;
|
||||
|
||||
query II
|
||||
select * from tbl;
|
||||
----
|
||||
1 3
|
||||
2 4
|
||||
3 10
|
||||
4 3
|
||||
83
external/duckdb/test/sql/upsert/upsert_returning.test
vendored
Normal file
83
external/duckdb/test/sql/upsert/upsert_returning.test
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
# name: test/sql/upsert/upsert_returning.test
|
||||
# group: [upsert]
|
||||
|
||||
require vector_size 2048
|
||||
|
||||
statement ok
|
||||
CREATE TABLE users (
|
||||
id BIGINT PRIMARY KEY,
|
||||
username TEXT UNIQUE,
|
||||
email TEXT
|
||||
);
|
||||
|
||||
query III
|
||||
INSERT INTO users (id, username, email) VALUES
|
||||
(1, 'john_doe', 'john@example.com')
|
||||
ON CONFLICT (username) DO NOTHING
|
||||
RETURNING *;
|
||||
----
|
||||
1 john_doe john@example.com
|
||||
|
||||
query III
|
||||
INSERT INTO users (id, username, email) VALUES
|
||||
(1, 'john_doe', 'john@example.com')
|
||||
ON CONFLICT (username) DO NOTHING
|
||||
RETURNING *;
|
||||
----
|
||||
|
||||
# We create a conflict, with a where clause that filters out this conflict
|
||||
# Because the where clause filters it out, the DO UPDATE becomes a DO NOTHING for this row instead
|
||||
# So it does not get added to the returning clause.
|
||||
query III
|
||||
INSERT INTO users (id, username, email)
|
||||
VALUES (1, 'john_doe', 'john_new@example.com')
|
||||
ON CONFLICT (id) DO
|
||||
UPDATE SET email = EXCLUDED.email
|
||||
WHERE EXCLUDED.email != 'john_new@example.com'
|
||||
RETURNING *;
|
||||
----
|
||||
|
||||
# Verify that the *other* tuple does get added to the returning clause
|
||||
query III
|
||||
INSERT INTO users (id, username, email)
|
||||
VALUES
|
||||
(1, 'john_doe', 'john_new@example.com'),
|
||||
(2, 'not_john_doe', 'not_john_new@example.com')
|
||||
ON CONFLICT (id) DO
|
||||
UPDATE SET email = EXCLUDED.email
|
||||
WHERE EXCLUDED.email != 'john_new@example.com'
|
||||
RETURNING *;
|
||||
----
|
||||
2 not_john_doe not_john_new@example.com
|
||||
|
||||
|
||||
# FIXME: not consistent
|
||||
mode skip
|
||||
|
||||
# Here we have conflicts within the inserted data
|
||||
# Only the last occurrence of this conflict should be present in the returning clause.
|
||||
query III
|
||||
INSERT INTO users (id, username, email)
|
||||
VALUES
|
||||
(3, 'inner_conflict', 'test'),
|
||||
(4, 'a', ''),
|
||||
(5, 'b', ''),
|
||||
(6, 'c', ''),
|
||||
(3, 'inner_conflict2', 'other_test'),
|
||||
(7, 'd', ''),
|
||||
(8, 'e', ''),
|
||||
(9, 'f', ''),
|
||||
(3, 'inner_conflict3', 'yet_another_test')
|
||||
ON CONFLICT (id) DO
|
||||
UPDATE SET email = EXCLUDED.email
|
||||
WHERE EXCLUDED.email != 'test'
|
||||
RETURNING *;
|
||||
----
|
||||
3 inner_conflict test
|
||||
4 a (empty)
|
||||
5 b (empty)
|
||||
6 c (empty)
|
||||
7 d (empty)
|
||||
8 e (empty)
|
||||
9 f (empty)
|
||||
3 inner_conflict3 yet_another_test
|
||||
56
external/duckdb/test/sql/upsert/upsert_set_expressions.test
vendored
Normal file
56
external/duckdb/test/sql/upsert/upsert_set_expressions.test
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
# name: test/sql/upsert/upsert_set_expressions.test
|
||||
# group: [upsert]
|
||||
|
||||
statement ok
|
||||
pragma enable_verification;
|
||||
|
||||
# Create a table with only 1 non-indexed column
|
||||
statement ok
|
||||
create or replace table tbl(
|
||||
i integer PRIMARY KEY,
|
||||
j integer UNIQUE,
|
||||
k integer
|
||||
);
|
||||
|
||||
# Add 3 rows
|
||||
statement ok
|
||||
insert into tbl VALUES
|
||||
(1, 10, 1),
|
||||
(2, 20, 1),
|
||||
(3, 30, 2);
|
||||
|
||||
# the 'i' column is indexed on and 3 already exists, causes a conflict
|
||||
# this updates 'k' to 5
|
||||
statement ok
|
||||
insert into tbl VALUES (3,5,1) ON CONFLICT (i) DO UPDATE SET k = 5;
|
||||
|
||||
query III
|
||||
select * from tbl;
|
||||
----
|
||||
1 10 1
|
||||
2 20 1
|
||||
3 30 5
|
||||
|
||||
# the 'i' column is indexed on and 3 already exists, causes a conflict
|
||||
# this updates 'k' to 1 + excluded.k
|
||||
statement ok
|
||||
insert into tbl VALUES (3,5,1) ON CONFLICT (i) DO UPDATE SET k = 1 + excluded.k;
|
||||
|
||||
query III
|
||||
select * from tbl;
|
||||
----
|
||||
1 10 1
|
||||
2 20 1
|
||||
3 30 2
|
||||
|
||||
# the 'i' column is indexed on and 3 already exists, causes a conflict
|
||||
# this updates 'k' to k + excluded.k
|
||||
statement ok
|
||||
insert into tbl VALUES (3,5,1) ON CONFLICT (i) DO UPDATE SET k = k + excluded.k;
|
||||
|
||||
query III
|
||||
select * from tbl;
|
||||
----
|
||||
1 10 1
|
||||
2 20 1
|
||||
3 30 3
|
||||
43
external/duckdb/test/sql/upsert/upsert_shorthand.test
vendored
Normal file
43
external/duckdb/test/sql/upsert/upsert_shorthand.test
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
# name: test/sql/upsert/upsert_shorthand.test
|
||||
# group: [upsert]
|
||||
|
||||
statement ok
|
||||
pragma enable_verification;
|
||||
|
||||
statement ok
|
||||
create table tbl (a integer, b integer unique);
|
||||
|
||||
statement ok
|
||||
insert into tbl values (1,2), (2,1);
|
||||
|
||||
statement ok
|
||||
insert into tbl values (1,2) on conflict do update set a = excluded.a;
|
||||
|
||||
# We can not supply both a shorthand and a verbose version of the ON CONFLICT clause
|
||||
statement error
|
||||
insert or replace into tbl values (4,3) on conflict do nothing;
|
||||
----
|
||||
<REGEX>:.*Parser Error.*You can not provide both OR.*
|
||||
|
||||
# INSERT OR IGNORE is shorthand for DO NOTHING
|
||||
statement ok
|
||||
insert or ignore into tbl values (1,2), (2,1);
|
||||
|
||||
# INSERT OR REPLACE is shorthand for DO UPDATE SET a = excluded.a, SET b = excluded.b;
|
||||
statement ok
|
||||
insert or replace into tbl values (5,2), (10,1);
|
||||
|
||||
query II
|
||||
select * from tbl;
|
||||
----
|
||||
5 2
|
||||
10 1
|
||||
|
||||
statement ok
|
||||
create or replace table tbl (a integer unique, b integer unique);
|
||||
|
||||
# When there is more than 1 index on the table, OR REPLACE is not supported, just like DO UPDATE
|
||||
statement error
|
||||
insert or replace into tbl values (1,2);
|
||||
----
|
||||
<REGEX>:.*Binder Error.*Conflict target has to be provided for a DO UPDATE.*
|
||||
134
external/duckdb/test/sql/upsert/upsert_transaction.test
vendored
Normal file
134
external/duckdb/test/sql/upsert/upsert_transaction.test
vendored
Normal file
@@ -0,0 +1,134 @@
|
||||
# name: test/sql/upsert/upsert_transaction.test
|
||||
# group: [upsert]
|
||||
|
||||
# This tests the desired behavior when UPSERT is used on a conflict that only exists within the transaction local storage.
|
||||
# NOTE: This does not test behavior of conflicts that arise between transactions
|
||||
|
||||
# DO UPDATE
|
||||
|
||||
statement ok
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
statement ok
|
||||
CREATE TABLE tbl (
|
||||
a SHORT PRIMARY KEY,
|
||||
b SHORT
|
||||
);
|
||||
|
||||
statement ok
|
||||
INSERT INTO tbl VALUES
|
||||
(1, 2)
|
||||
ON CONFLICT (a) DO UPDATE SET b = excluded.b;
|
||||
|
||||
# Create a conflict within the transaction
|
||||
statement ok
|
||||
INSERT INTO tbl VALUES
|
||||
(1, 3)
|
||||
ON CONFLICT (a) DO UPDATE SET b = excluded.b;
|
||||
|
||||
query II
|
||||
select * from tbl;
|
||||
----
|
||||
1 3
|
||||
|
||||
statement ok
|
||||
COMMIT;
|
||||
|
||||
query II
|
||||
select * from tbl;
|
||||
----
|
||||
1 3
|
||||
|
||||
# DO NOTHING
|
||||
|
||||
statement ok
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
statement ok
|
||||
INSERT INTO tbl VALUES
|
||||
(2, 1),
|
||||
(3, 1),
|
||||
(4, 1);
|
||||
|
||||
statement ok
|
||||
INSERT INTO tbl VALUES
|
||||
(2, 1),
|
||||
(3, 1),
|
||||
(4, 1)
|
||||
ON CONFLICT (a) DO NOTHING;
|
||||
|
||||
statement ok
|
||||
COMMIT;
|
||||
|
||||
# Attempt to update the same row twice within the same UPSERT
|
||||
statement ok
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
statement ok
|
||||
INSERT INTO tbl VALUES
|
||||
(5, 0)
|
||||
|
||||
statement ok
|
||||
insert into tbl VALUES
|
||||
(5, 0),
|
||||
(5, 1)
|
||||
ON CONFLICT (a) DO UPDATE SET
|
||||
b = excluded.b;
|
||||
|
||||
statement ok
|
||||
COMMIT;
|
||||
|
||||
# DO UPDATE 'affected_tuples' return value
|
||||
|
||||
statement ok
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
statement ok
|
||||
INSERT INTO tbl VALUES (6,0);
|
||||
|
||||
# Both of these inserts turn into updates
|
||||
# The first affected tuple (5) is an update in the global storage
|
||||
# The second affected tuple (6) is an update in the local storage
|
||||
# The third affected tuple is an insert into the local storage
|
||||
query I
|
||||
INSERT INTO tbl VALUES (5,0), (6,0), (7,0) ON CONFLICT (a) DO UPDATE set b = excluded.b;
|
||||
----
|
||||
3
|
||||
|
||||
# The only affected tuple is the insert into the local storage
|
||||
# (5,0) causes a constraint error in the global storage
|
||||
# (3,0) causes a constraint error in the local storage
|
||||
query I
|
||||
INSERT INTO tbl VALUES (-1, 0), (5,0), (6,0) ON CONFLICT (a) DO NOTHING;
|
||||
----
|
||||
1
|
||||
|
||||
statement ok
|
||||
COMMIT;
|
||||
|
||||
# DO UPDATE > STANDARD_VECTOR_SIZE
|
||||
|
||||
statement ok
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
statement ok
|
||||
CREATE OR REPLACE TABLE tbl (a SHORT PRIMARY KEY, b SHORT);
|
||||
|
||||
statement ok
|
||||
INSERT INTO tbl (select i, 0 from range(2500) tbl(i));
|
||||
|
||||
query I
|
||||
select max(b) from tbl;
|
||||
----
|
||||
0
|
||||
|
||||
statement ok
|
||||
INSERT INTO tbl (select i, i from range(2500) tbl(i)) ON CONFLICT (a) DO UPDATE SET b = excluded.b;
|
||||
|
||||
query I
|
||||
select max(b) from tbl;
|
||||
----
|
||||
2499
|
||||
|
||||
statement ok
|
||||
COMMIT;
|
||||
37
external/duckdb/test/sql/upsert/upsert_unique_null.test
vendored
Normal file
37
external/duckdb/test/sql/upsert/upsert_unique_null.test
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
# name: test/sql/upsert/upsert_unique_null.test
|
||||
# group: [upsert]
|
||||
|
||||
statement ok
|
||||
pragma enable_verification;
|
||||
|
||||
statement ok
|
||||
create or replace table tbl (
|
||||
a integer unique,
|
||||
b integer
|
||||
);
|
||||
|
||||
statement ok
|
||||
insert into tbl VALUES (3,2), (1,3);
|
||||
|
||||
statement ok
|
||||
insert into tbl(b) VALUES (5) ON CONFLICT (a) DO UPDATE SET b = 8;
|
||||
|
||||
# UNIQUE can be NULL, PRIMARY KEY can't be
|
||||
query II
|
||||
select * from tbl;
|
||||
----
|
||||
3 2
|
||||
1 3
|
||||
NULL 5
|
||||
|
||||
statement ok
|
||||
insert into tbl(b) VALUES (5) ON CONFLICT (a) DO UPDATE SET b = 8;
|
||||
|
||||
# And NULL does not take part in the UNIQUE Index, so it does not activate the ON CONFLICT clause
|
||||
query II
|
||||
select * from tbl;
|
||||
----
|
||||
3 2
|
||||
1 3
|
||||
NULL 5
|
||||
NULL 5
|
||||
Reference in New Issue
Block a user