UPSERT test case

This commit is contained in:
gentle_hu 2020-08-22 14:01:20 +08:00
parent ec6bdc4f11
commit ca5f135273
51 changed files with 7161 additions and 74 deletions

View File

@ -2,6 +2,9 @@ DROP SCHEMA test_insert_update_001 CASCADE;
ERROR: schema "test_insert_update_001" does not exist
CREATE SCHEMA test_insert_update_001;
SET CURRENT_SCHEMA TO test_insert_update_001;
-- SET enable_upsert_to_merge=ON to test the upsert implemented by merge,
-- real upsert will be tested in specialized case.
SET enable_upsert_to_merge TO ON;
-- test description
\h INSERT
Command: INSERT

View File

@ -2,6 +2,9 @@ DROP SCHEMA test_insert_update_002 CASCADE;
ERROR: schema "test_insert_update_002" does not exist
CREATE SCHEMA test_insert_update_002;
SET CURRENT_SCHEMA TO test_insert_update_002;
-- SET enable_upsert_to_merge=ON to test the upsert implemented by merge,
-- real upsert will be tested in specialized case.
SET enable_upsert_to_merge TO ON;
-- test t1 with no index
CREATE TABLE t1 (
col1 INT,

View File

@ -2,6 +2,9 @@ DROP SCHEMA test_insert_update_003 CASCADE;
ERROR: schema "test_insert_update_003" does not exist
CREATE SCHEMA test_insert_update_003;
SET CURRENT_SCHEMA TO test_insert_update_003;
-- SET enable_upsert_to_merge=ON to test the upsert implemented by merge,
-- real upsert will be tested in specialized case.
SET enable_upsert_to_merge TO ON;
-- test t4 with one primary key with three columns
CREATE TABLE t4 (
col1 INT,

View File

@ -4,6 +4,9 @@
-- initial
CREATE SCHEMA test_insert_update_008;
SET current_schema = test_insert_update_008;
-- SET enable_upsert_to_merge=ON to test the upsert implemented by merge,
-- real upsert will be tested in specialized case.
SET enable_upsert_to_merge TO ON;
CREATE TABLE products_base
(
product_id INTEGER DEFAULT 0,
@ -58,9 +61,9 @@ EXPLAIN (VERBOSE on, COSTS off)
INSERT INTO products_row
SELECT product_id, product_name, category, total FROM newproducts_row
ON DUPLICATE KEY UPDATE
product_name = __unnamed_subquery_source__.product_name,
category = __unnamed_subquery_source__.category,
total = __unnamed_subquery_source__.total;
product_name = excluded.product_name,
category = excluded.category,
total = excluded.total;
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Merge on test_insert_update_008.products_row
@ -84,9 +87,9 @@ INSERT INTO products_row
FROM newproducts_row, products_row
WHERE products_row.total + newproducts_row.total < 1000
ON DUPLICATE KEY UPDATE
product_name = __unnamed_subquery_source__.product_name,
category = __unnamed_subquery_source__.category,
total = __unnamed_subquery_source__.total;
product_name = excluded.product_name,
category = excluded.category,
total = excluded.total;
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Merge on test_insert_update_008.products_row
@ -113,9 +116,9 @@ INSERT INTO products_row
SELECT product_id, product_name, category, total
FROM newproducts_row WHERE product_id IS NOT NULL AND product_name IS NOT NULL
ON DUPLICATE KEY UPDATE
product_name = __unnamed_subquery_source__.product_name,
category = __unnamed_subquery_source__.category,
total = __unnamed_subquery_source__.total;
product_name = excluded.product_name,
category = excluded.category,
total = excluded.total;
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Merge on test_insert_update_008.products_row
@ -137,9 +140,9 @@ EXPLAIN (ANALYZE on, COSTS off, TIMING off)
INSERT INTO products_row
SELECT product_id, product_name, category, total FROM newproducts_row
ON DUPLICATE KEY UPDATE
product_name = __unnamed_subquery_source__.product_name,
category = __unnamed_subquery_source__.category,
total = __unnamed_subquery_source__.total;
product_name = excluded.product_name,
category = excluded.category,
total = excluded.total;
QUERY PLAN
---------------------------------------------------------------------------
Merge on products_row (actual rows=4 loops=1)
@ -162,9 +165,9 @@ EXPLAIN PERFORMANCE
INSERT INTO products_row
SELECT product_id, product_name, category, total FROM newproducts_row
ON DUPLICATE KEY UPDATE
product_name = __unnamed_subquery_source__.product_name,
category = __unnamed_subquery_source__.category,
total = __unnamed_subquery_source__.total;
product_name = excluded.product_name,
category = excluded.category,
total = excluded.total;
ROLLBACK;
\o
-- explain analyze
@ -173,9 +176,9 @@ EXPLAIN (ANALYZE on, COSTS off, TIMING off)
INSERT INTO products_row
SELECT product_id, product_name, category, total FROM newproducts_row
ON DUPLICATE KEY UPDATE
product_name = __unnamed_subquery_source__.product_name,
category = __unnamed_subquery_source__.category,
total = __unnamed_subquery_source__.total;
product_name = excluded.product_name,
category = excluded.category,
total = excluded.total;
QUERY PLAN
---------------------------------------------------------------------------
Merge on products_row (actual rows=4 loops=1)
@ -198,9 +201,9 @@ EXPLAIN (VERBOSE on, COSTS off)
INSERT INTO products_row
SELECT product_id, product_name, category, total FROM newproducts_row
ON DUPLICATE KEY UPDATE
product_name = __unnamed_subquery_source__.product_name,
category = __unnamed_subquery_source__.category,
total = __unnamed_subquery_source__.total;
product_name = excluded.product_name,
category = excluded.category,
total = excluded.total;
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Merge on test_insert_update_008.products_row
@ -221,9 +224,9 @@ EXPLAIN (ANALYZE on, COSTS off, TIMING off)
INSERT INTO products_row
SELECT product_id, product_name, category, total FROM newproducts_row
ON DUPLICATE KEY UPDATE
product_name = __unnamed_subquery_source__.product_name,
category = __unnamed_subquery_source__.category,
total = __unnamed_subquery_source__.total;
product_name = excluded.product_name,
category = excluded.category,
total = excluded.total;
QUERY PLAN
---------------------------------------------------------------------------
Merge on products_row (actual rows=4 loops=1)
@ -245,9 +248,9 @@ EXPLAIN (ANALYZE on, COSTS off, TIMING off)
INSERT INTO products_row
SELECT product_id, product_name, category, total FROM newproducts_row
ON DUPLICATE KEY UPDATE
product_name = __unnamed_subquery_source__.product_name,
category = __unnamed_subquery_source__.category,
total = __unnamed_subquery_source__.total;
product_name = excluded.product_name,
category = excluded.category,
total = excluded.total;
QUERY PLAN
---------------------------------------------------------------------------
Merge on products_row (actual rows=4 loops=1)
@ -270,9 +273,9 @@ EXPLAIN PERFORMANCE
INSERT INTO products_row
SELECT product_id, product_name, category, total FROM newproducts_row
ON DUPLICATE KEY UPDATE
product_name = __unnamed_subquery_source__.product_name,
category = __unnamed_subquery_source__.category,
total = __unnamed_subquery_source__.total;
product_name = excluded.product_name,
category = excluded.category,
total = excluded.total;
ROLLBACK;
SET explain_perf_mode = run;
BEGIN;
@ -280,9 +283,9 @@ EXPLAIN PERFORMANCE
INSERT INTO products_row
SELECT product_id, product_name, category, total FROM newproducts_row
ON DUPLICATE KEY UPDATE
product_name = __unnamed_subquery_source__.product_name,
category = __unnamed_subquery_source__.category,
total = __unnamed_subquery_source__.total;
product_name = excluded.product_name,
category = excluded.category,
total = excluded.total;
ROLLBACK;
SET explain_perf_mode = summary;
BEGIN;
@ -290,9 +293,9 @@ EXPLAIN PERFORMANCE
INSERT INTO products_row
SELECT product_id, product_name, category, total FROM newproducts_row
ON DUPLICATE KEY UPDATE
product_name = __unnamed_subquery_source__.product_name,
category = __unnamed_subquery_source__.category,
total = __unnamed_subquery_source__.total;
product_name = excluded.product_name,
category = excluded.category,
total = excluded.total;
ROLLBACK;
\o
CREATE TABLE item

View File

@ -3,6 +3,9 @@ ERROR: schema "test_insert_update_009" does not exist
CREATE SCHEMA test_insert_update_009;
SET CURRENT_SCHEMA TO test_insert_update_009;
SET enable_light_proxy=off;
-- SET enable_upsert_to_merge=ON to test the upsert implemented by merge,
-- real upsert will be tested in specialized case.
SET enable_upsert_to_merge TO ON;
-- test t1 with no index
CREATE TABLE t1 (
col1 INT,

View File

@ -2,6 +2,9 @@ DROP SCHEMA test_insert_update_010 CASCADE;
ERROR: schema "test_insert_update_010" does not exist
CREATE SCHEMA test_insert_update_010;
SET CURRENT_SCHEMA TO test_insert_update_010;
-- SET enable_upsert_to_merge=ON to test the upsert implemented by merge,
-- real upsert will be tested in specialized case.
SET enable_upsert_to_merge TO ON;
-- test t4 with one primary key with three columns
CREATE TABLE t4 (
col1 INT,

View File

@ -1,3 +1,6 @@
-- SET enable_upsert_to_merge=ON to test the upsert implemented by merge,
-- real upsert will be tested in specialized case.
SET enable_upsert_to_merge TO ON;
SELECT name, setting FROM pg_settings WHERE name LIKE 'enable%' ORDER BY name;
name | setting
-----------------------------------+---------
@ -74,12 +77,13 @@ SELECT name, setting FROM pg_settings WHERE name LIKE 'enable%' ORDER BY name;
enable_thread_pool | off
enable_tidscan | on
enable_upgrade_merge_lock_mode | off
enable_upsert_to_merge | on
enable_user_metric_persistent | on
enable_valuepartition_pruning | on
enable_vector_engine | on
enable_wdr_snapshot | off
enable_xlog_prune | on
(78 rows)
(79 rows)
CREATE TABLE foo2(fooid int, f2 int);
INSERT INTO foo2 VALUES(1, 11);

View File

@ -0,0 +1,515 @@
DROP SCHEMA test_upsert_001 CASCADE;
ERROR: schema "test_upsert_001" does not exist
CREATE SCHEMA test_upsert_001;
SET CURRENT_SCHEMA TO test_upsert_001;
-- enable_upsert_to_merge must is off, or upsert will be translated to merge.
SET enable_upsert_to_merge TO OFF;
-- test description
\h INSERT
Command: INSERT
Description: create new rows in a table
Syntax:
[ WITH [ RECURSIVE ] with_query [, ...] ]
INSERT INTO table_name [ ( column_name [, ...] ) ]
{ DEFAULT VALUES | VALUES {( { expression | DEFAULT } [, ...] ) }[, ...] | query }
[ ON DUPLICATE KEY UPDATE { column_name = { expression | DEFAULT } } [, ...] ]
[ RETURNING {* | {output_expression [ [ AS ] output_name ] }[, ...]} ];
-- test permission
--- test with no sequence column
CREATE TABLE t00 (col1 INT DEFAULT 1 PRIMARY KEY, col2 INT);
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "t00_pkey" for table "t00"
CREATE USER upsert_tester PASSWORD '123456@cc';
GRANT ALL PRIVILEGES ON SCHEMA test_upsert_001 TO upsert_tester;
SET SESSION SESSION AUTHORIZATION upsert_tester PASSWORD '123456@cc';
INSERT INTO test_upsert_001.t00 VALUES(1) ON DUPLICATE KEY UPDATE col2 = 5;
ERROR: permission denied for relation t00
RESET SESSION AUTHORIZATION;
---- error: only have INSERT permission
GRANT INSERT ON test_upsert_001.t00 TO upsert_tester;
SET SESSION SESSION AUTHORIZATION upsert_tester PASSWORD '123456@cc';
INSERT INTO test_upsert_001.t00 VALUES(1) ON DUPLICATE KEY UPDATE col2 = 5;
ERROR: permission denied for relation t00
RESET SESSION AUTHORIZATION;
---- success: have INSERT UPDATE permission
GRANT INSERT, UPDATE ON test_upsert_001.t00 TO upsert_tester;
SET SESSION SESSION AUTHORIZATION upsert_tester PASSWORD '123456@cc';
INSERT INTO test_upsert_001.t00 VALUES(1) ON DUPLICATE KEY UPDATE col2 = 5;
RESET SESSION AUTHORIZATION;
--- have SELECT INSERT UPDATE permission
GRANT SELECT, INSERT, UPDATE ON test_upsert_001.t00 TO upsert_tester;
SET SESSION SESSION AUTHORIZATION upsert_tester PASSWORD '123456@cc';
INSERT INTO test_upsert_001.t00 VALUES(1) ON DUPLICATE KEY UPDATE col2 = 5;
INSERT INTO test_upsert_001.t00 VALUES(1) ON DUPLICATE KEY UPDATE col3 = 5;
ERROR: column "col3" of relation "t00" does not exist
LINE 1: ...t_upsert_001.t00 VALUES(1) ON DUPLICATE KEY UPDATE col3 = 5;
^
RESET SESSION AUTHORIZATION;
--- test with sequnce column
CREATE TABLE t01 (col1 INT , col2 BIGSERIAL PRIMARY KEY, col3 INT) ;
NOTICE: CREATE TABLE will create implicit sequence "t01_col2_seq" for serial column "t01.col2"
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "t01_pkey" for table "t01"
---- error: don't have UPDATE permission on sequence table.
GRANT SELECT, INSERT, UPDATE ON test_upsert_001.t01 TO upsert_tester;
SET SESSION SESSION AUTHORIZATION upsert_tester PASSWORD '123456@cc';
INSERT INTO test_upsert_001.t01 VALUES(1) ON DUPLICATE KEY UPDATE col3 = 5;
ERROR: permission denied for sequence t01_col2_seq
CONTEXT: referenced column: col2
RESET SESSION AUTHORIZATION;
---- have SELECT INSERT UPDATE permission on target relation, and UPDATE permission on sequence table.
GRANT UPDATE ON test_upsert_001.t01_col2_seq TO upsert_tester;
SET SESSION SESSION AUTHORIZATION upsert_tester PASSWORD '123456@cc';
INSERT INTO test_upsert_001.t01 VALUES(1) ON DUPLICATE KEY UPDATE col3 = 5;
INSERT INTO test_upsert_001.t01 VALUES(1) ON DUPLICATE KEY UPDATE col3 = 5;
RESET SESSION AUTHORIZATION;
-- test ommit INSERT target column
CREATE TABLE t02 (col1 INT DEFAULT 1 PRIMARY KEY, col2 INT, col3 INT);
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "t02_pkey" for table "t02"
INSERT INTO t02 VALUES(1, 2, 3) ON DUPLICATE KEY UPDATE col2 = 20;
SELECT * FROM t02 ORDER BY 1, 2;
col1 | col2 | col3
------+------+------
1 | 2 | 3
(1 row)
INSERT INTO t02 VALUES(1, 2, 3) ON DUPLICATE KEY UPDATE col2 = 20;
SELECT * FROM t02 ORDER BY 1, 2;
col1 | col2 | col3
------+------+------
1 | 20 | 3
(1 row)
ALTER TABLE t02 DROP COLUMN col2;
ALTER TABLE t02 ADD COLUMN col4 INT;
INSERT INTO t02 VALUES(1, 2, 3) ON DUPLICATE KEY UPDATE col4 = 40;
SELECT * FROM t02 ORDER BY 1, 2;
col1 | col3 | col4
------+------+------
1 | 3 | 40
(1 row)
INSERT INTO t02 VALUES(2, 3, 4) ON DUPLICATE KEY UPDATE col4 = 40;
SELECT * FROM t02 ORDER BY 1, 2;
col1 | col3 | col4
------+------+------
1 | 3 | 40
2 | 3 | 4
(2 rows)
INSERT INTO t02 VALUES(2, 3, 4) ON DUPLICATE KEY UPDATE col4 = 40;
SELECT * FROM t02 ORDER BY 1, 2;
col1 | col3 | col4
------+------+------
1 | 3 | 40
2 | 3 | 40
(2 rows)
-- test restriction
--- test replication table
CREATE TABLE t03 (col1 int PRIMARY KEY, col2 INT, col3 smallserial) ;
NOTICE: CREATE TABLE will create implicit sequence "t03_col3_seq" for serial column "t03.col3"
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "t03_pkey" for table "t03"
--- error: not allowed volatile function as default value
INSERT INTO t03(col2) VALUES(1) ON DUPLICATE KEY UPDATE col2 = 100;
ERROR: null value in column "col1" violates not-null constraint
DETAIL: Failing row contains (null, 1, 1).
ALTER TABLE t03 DROP COLUMN col3;
--- error: primary key are not allowed to update
INSERT INTO t03 VALUES(1) ON DUPLICATE KEY UPDATE col1 = 1;
ERROR: INSERT ON DUPLICATE KEY UPDATE don't allow update on primary key or unique key.
--- error: clause other than VALUSES are not allowed to use
INSERT INTO t03 SELECT * FROM t03 ON DUPLICATE KEY UPDATE col2 = 1;
--- success: expression index are supported
CREATE UNIQUE INDEX u_expr_index ON t03 USING btree (abs(col1));
INSERT INTO t03 VALUES(-10, 10) ON DUPLICATE KEY UPDATE col2 = 20;
DROP INDEX u_expr_index;
-- test with stream operator on
INSERT INTO t03 VALUES(1) ON DUPLICATE KEY UPDATE col2 = 100;
SELECT * FROM t03;
col1 | col2
------+------
-10 | 10
1 |
(2 rows)
INSERT INTO t03 VALUES(1) ON DUPLICATE KEY UPDATE col2 = 100;
SELECT * FROM t03;
col1 | col2
------+------
-10 | 10
1 | 100
(2 rows)
SELECT * FROM t03;
col1 | col2
------+------
-10 | 10
1 | 100
(2 rows)
--- test PBE
PREPARE p1 AS INSERT INTO t03 VALUES($1, $2) ON DUPLICATE KEY UPDATE col2 = $1*100;
EXECUTE p1(5, 50);
SELECT * FROM t03 WHERE col1 = 5;
col1 | col2
------+------
5 | 50
(1 row)
EXECUTE p1(5, 50);
SELECT * FROM t03 WHERE col1 = 5;
col1 | col2
------+------
5 | 500
(1 row)
DELETE t03 WHERE col1 = 5;
---- test with primary key
INSERT INTO t03 VALUES(2) ON DUPLICATE KEY UPDATE col2 = 200;
SELECT * FROM t03;
col1 | col2
------+------
-10 | 10
1 | 100
2 |
(3 rows)
INSERT INTO t03 VALUES(2) ON DUPLICATE KEY UPDATE col2 = 200;
SELECT * FROM t03;
col1 | col2
------+------
-10 | 10
1 | 100
2 | 200
(3 rows)
SELECT * FROM t03;
col1 | col2
------+------
-10 | 10
1 | 100
2 | 200
(3 rows)
---- test with unique key without NOT NULL constraint
ALTER TABLE t03 DROP CONSTRAINT t03_pkey;
ALTER TABLE t03 ADD COLUMN col3 INT;
CREATE UNIQUE INDEX ON t03 (col1, col3);
---- unique constraints might contain NULL, depends on the plan
----- for cn light and fqs, it can be done
INSERT INTO t03 VALUES(3) ON DUPLICATE KEY UPDATE col2 = 300;
----- for stream or pgxc it can not be done
INSERT INTO t03 VALUES(3) ON DUPLICATE KEY UPDATE col2 = 300;
---- test with unique key with NOT NULL constraint, should success
CREATE UNIQUE INDEX ON t03 (col1);
ERROR: could not create unique index "t03_col1_idx"
DETAIL: Key (col1)=(3) is duplicated.
INSERT INTO t03 VALUES(3) ON DUPLICATE KEY UPDATE col2 = 300;
SELECT * FROM t03;
col1 | col2 | col3
------+------+------
-10 | 10 |
1 | 100 |
2 | 200 |
3 | |
3 | |
3 | |
(6 rows)
INSERT INTO t03 VALUES(3) ON DUPLICATE KEY UPDATE col2 = 300;
SELECT * FROM t03;
col1 | col2 | col3
------+------+------
-10 | 10 |
1 | 100 |
2 | 200 |
3 | |
3 | |
3 | |
3 | |
(7 rows)
SELECT * FROM t03;
col1 | col2 | col3
------+------+------
-10 | 10 |
1 | 100 |
2 | 200 |
3 | |
3 | |
3 | |
3 | |
(7 rows)
---- test PBE
PREPARE p2 AS INSERT INTO t03 VALUES($1, $2) ON DUPLICATE KEY UPDATE col2 = $1*100;
EXECUTE p2(5, 50);
SELECT * FROM t03 WHERE col1 = 5;
col1 | col2 | col3
------+------+------
5 | 50 |
(1 row)
EXECUTE p2(5, 50);
SELECT * FROM t03 WHERE col1 = 5;
col1 | col2 | col3
------+------+------
5 | 50 |
5 | 50 |
(2 rows)
--- error: test with clause
WITH tmp(col1, col2) AS (SELECT * FROM t01)
INSERT INTO t01 SELECT * FROM tmp ON DUPLICATE KEY UPDATE col1 = 1;
ERROR: WITH clause is not yet supported whithin INSERT ON DUPLICATE KEY UPDATE statement.
WITH RECURSIVE rq AS
(
SELECT col1, col2 FROM t00 WHERE col1 = 1
UNION ALL
SELECT origin.col1, rq.col2
FROM rq JOIN t00 AS origin ON origin.col1 = rq.col1
)
INSERT INTO t03 SELECT * FROM rq ON DUPLICATE KEY UPDATE col1 = rq.col1;
ERROR: WITH clause is not yet supported whithin INSERT ON DUPLICATE KEY UPDATE statement.
--- error: test returning clause
INSERT INTO t01 VALUES (1) ON DUPLICATE KEY UPDATE col1 = 1 RETURNING NOT(1::bool);
ERROR: RETURNING clause is not yet supported whithin INSERT ON DUPLICATE KEY UPDATE statement.
--- error: distribute key are not allowed to UPDATE
CREATE TABLE t04 (col1 INT, col2 INT) ;
INSERT INTO t04 VALUES (1) ON DUPLICATE KEY UPDATE col1 = 5;
--- error: unique index referenced column are not allowed to UPDATE
CREATE UNIQUE INDEX t04_u_index ON t04(col1, col2);
INSERT INTO t04 VALUES (1) ON DUPLICATE KEY UPDATE col2 = 5;
ERROR: INSERT ON DUPLICATE KEY UPDATE don't allow update on primary key or unique key.
DROP INDEX t04_u_index;
--- error: primary key referenced column are not allowed to UPDATE
ALTER TABLE t04 ADD PRIMARY KEY (col1, col2);
ERROR: column "col2" contains null values
INSERT INTO t04 VALUES (1) ON DUPLICATE KEY UPDATE col2 = 5;
--- error: invalid column
INSERT INTO t04 (col2, col3) VALUES (2, 3) ON DUPLICATE KEY UPDATE col2 = 5;
ERROR: column "col3" of relation "t04" does not exist
LINE 1: INSERT INTO t04 (col2, col3) VALUES (2, 3) ON DUPLICATE KEY ...
^
--- error: duplicate column
INSERT INTO t04 (col2, col2) VALUES (2, 3) ON DUPLICATE KEY UPDATE col2 = 5;
ERROR: column "col2" specified more than once
LINE 1: INSERT INTO t04 (col2, col2) VALUES (2, 3) ON DUPLICATE KEY ...
^
-- error: target column more than insert target
INSERT INTO t04 (col1, col2) VALUES (2, 3, 4) ON DUPLICATE KEY UPDATE col2 = 5;
ERROR: INSERT has more expressions than target columns
LINE 1: INSERT INTO t04 (col1, col2) VALUES (2, 3, 4) ON DUPLICATE K...
^
INSERT INTO t04 (col1, col2) VALUES (1) ON DUPLICATE KEY UPDATE col2 = 5;
ERROR: INSERT has more target columns than expressions
LINE 1: INSERT INTO t04 (col1, col2) VALUES (1) ON DUPLICATE KEY UPD...
^
INSERT INTO t04 (col1, col2) SELECT col1 FROM t04 ON DUPLICATE KEY UPDATE col2 = 5;
ERROR: INSERT has more target columns than expressions
LINE 1: INSERT INTO t04 (col1, col2) SELECT col1 FROM t04 ON DUPLICA...
^
INSERT INTO t04 (col1, col2) SELECT *, col1 FROM t04 ON DUPLICATE KEY UPDATE col2 = 5;
ERROR: INSERT has more expressions than target columns
LINE 1: INSERT INTO t04 (col1, col2) SELECT *, col1 FROM t04 ON DUPL...
^
INSERT INTO t04 VALUES (2, 3, 4) ON DUPLICATE KEY UPDATE col2 = 5;
ERROR: INSERT has more expressions than target columns
LINE 1: INSERT INTO t04 VALUES (2, 3, 4) ON DUPLICATE KEY UPDATE col...
^
INSERT INTO t04 VALUES (1) ON DUPLICATE KEY UPDATE col2 = 5;
INSERT INTO t04 SELECT col1 FROM t04 ON DUPLICATE KEY UPDATE col2 = 5;
INSERT INTO t04 SELECT *, col1 FROM t04 ON DUPLICATE KEY UPDATE col2 = 5;
ERROR: INSERT has more expressions than target columns
LINE 1: INSERT INTO t04 SELECT *, col1 FROM t04 ON DUPLICATE KEY UPD...
^
-- test DEFAULT VALUES
TRUNCATE t00;
TRUNCATE t01;
--- without sequence
----should insert
INSERT INTO t00 DEFAULT VALUES ON DUPLICATE KEY UPDATE col2 = col1;
SELECT * FROM t00 ORDER BY 1, 2;
col1 | col2
------+------
1 |
(1 row)
---- should update
INSERT INTO t00 DEFAULT VALUES ON DUPLICATE KEY UPDATE col2 = col1;
SELECT * FROM t00 ORDER BY 1, 2;
col1 | col2
------+------
1 | 1
(1 row)
--- test drop column
TRUNCATE t00;
ALTER TABLE t00 DROP COLUMN col2;
ALTER TABLE t00 ADD COLUMN col3 INT DEFAULT 100;
----should insert
INSERT INTO t00 DEFAULT VALUES ON DUPLICATE KEY UPDATE col3 = col1;
SELECT * FROM t00 ORDER BY 1, 2;
col1 | col3
------+------
1 | 100
(1 row)
---- should update
INSERT INTO t00 DEFAULT VALUES ON DUPLICATE KEY UPDATE col3 = col1;
SELECT * FROM t00 ORDER BY 1, 2;
col1 | col3
------+------
1 | 1
(1 row)
--- with sequence
----should insert
INSERT INTO t01 DEFAULT VALUES ON DUPLICATE KEY UPDATE col1 = col2;
INSERT INTO t01 (col2) SELECT col2 + 1 FROM t01 LIMIT 1;
SELECT * FROM t01 ORDER BY 1, 2, 3;
col1 | col2 | col3
------+------+------
| 3 |
| 4 |
(2 rows)
---- should update
INSERT INTO t01 DEFAULT VALUES ON DUPLICATE KEY UPDATE col1 = col2;
SELECT * FROM t01 ORDER BY 1, 2, 3;
col1 | col2 | col3
------+------+------
4 | 4 |
| 3 |
(2 rows)
-- test VALUES(DEFAULT)
CREATE TABLE t05 (col1 INT , col2 INT DEFAULT 1 PRIMARY KEY, col3 INT DEFAULT 100) ;
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "t05_pkey" for table "t05"
--- should insert
INSERT INTO t05 VALUES(DEFAULT) ON DUPLICATE KEY UPDATE col3 = 1000;
SELECT * FROM t05 ORDER BY 1, 2, 3;
col1 | col2 | col3
------+------+------
| 1 | 100
(1 row)
--- should update
INSERT INTO t05 VALUES(DEFAULT) ON DUPLICATE KEY UPDATE col3 = 1000;
SELECT * FROM t05 ORDER BY 1, 2, 3;
col1 | col2 | col3
------+------+------
| 1 | 1000
(1 row)
-- test UPDATE DEFAULT
INSERT INTO t05 (col1, col2, col3) VALUES (2, 2, 2) ON DUPLICATE KEY UPDATE col3 = DEFAULT;
SELECT * FROM t05 ORDER BY 1, 2, 3;
col1 | col2 | col3
------+------+------
2 | 2 | 2
| 1 | 1000
(2 rows)
INSERT INTO t05 (col1, col2, col3) VALUES (2, 2, 2) ON DUPLICATE KEY UPDATE col3 = DEFAULT;
SELECT * FROM t05 ORDER BY 1, 2, 3;
col1 | col2 | col3
------+------+------
2 | 2 | 100
| 1 | 1000
(2 rows)
-- test VALUES (DEFAULT, ...)
TRUNCATE t05;
--- should insert
INSERT INTO t05 VALUES(DEFAULT, DEFAULT, 200), (DEFAULT, 200, DEFAULT)
ON DUPLICATE KEY UPDATE col3 = DEFAULT, col1 = col3;
SELECT * FROM t05 ORDER BY 1, 2, 3;
col1 | col2 | col3
------+------+------
| 1 | 200
| 200 | 100
(2 rows)
--- should update
INSERT INTO t05 VALUES(DEFAULT, DEFAULT, 200), (DEFAULT, 200, DEFAULT)
ON DUPLICATE KEY UPDATE col3 = DEFAULT, col1 = col3;
SELECT * FROM t05 ORDER BY 1, 2, 3;
col1 | col2 | col3
------+------+------
100 | 200 | 100
200 | 1 | 100
(2 rows)
--- test drop coulmn
BEGIN;
ALTER TABLE t05 ADD COLUMN col4 INT;
ALTER TABLE t05 ADD COLUMN col5 INT DEFAULT 500;
ALTER TABLE t05 DROP COLUMN col3;
TRUNCATE t05;
INSERT INTO t05 VALUES(DEFAULT, DEFAULT, DEFAULT, 600) ON DUPLICATE KEY UPDATE col5 = DEFAULT;
SELECT * FROM t05 ORDER BY 1, 2, 3;
col1 | col2 | col4 | col5
------+------+------+------
| 1 | | 600
(1 row)
INSERT INTO t05 VALUES(DEFAULT, DEFAULT, DEFAULT, 600) ON DUPLICATE KEY UPDATE col5 = DEFAULT;
SELECT * FROM t05 ORDER BY 1, 2, 3;
col1 | col2 | col4 | col5
------+------+------+------
| 1 | | 500
(1 row)
ROLLBACK;
-- test schema
SET current_schema = public;
TRUNCATE test_upsert_001.t05;
--- should insert
INSERT INTO test_upsert_001.t05 VALUES(DEFAULT, DEFAULT, 200), (DEFAULT, 200, DEFAULT)
ON DUPLICATE KEY UPDATE col3 = DEFAULT, col1 = col3;
SELECT * FROM test_upsert_001.t05 ORDER BY 1, 2, 3;
col1 | col2 | col3
------+------+------
| 1 | 200
| 200 | 100
(2 rows)
--- should update
INSERT INTO test_upsert_001.t05 VALUES(DEFAULT, DEFAULT, 200), (DEFAULT, 200, DEFAULT)
ON DUPLICATE KEY UPDATE col3 = DEFAULT, col1 = col3;
SELECT * FROM test_upsert_001.t05 ORDER BY 1, 2, 3;
col1 | col2 | col3
------+------+------
100 | 200 | 100
200 | 1 | 100
(2 rows)
--- test using schema on update
INSERT INTO test_upsert_001.t05 VALUES(DEFAULT, DEFAULT, 200), (DEFAULT, 200, DEFAULT)
ON DUPLICATE KEY UPDATE t05.col3 = DEFAULT, t05.col1 = t05.col3 + 1;
SELECT * FROM test_upsert_001.t05 ORDER BY 1, 2, 3;
col1 | col2 | col3
------+------+------
101 | 1 | 100
101 | 200 | 100
(2 rows)
--- error: should not append schema
INSERT INTO test_upsert_001.t05 VALUES(DEFAULT, DEFAULT, 200), (DEFAULT, 200, DEFAULT)
ON DUPLICATE KEY UPDATE test_upsert_001.t05.col3 = DEFAULT, t05.col1 = t05.col3 + 1;
ERROR: column "test_upsert_001.t05" of relation "t05" does not exist
LINE 2: ON DUPLICATE KEY UPDATE test_upsert_001.t05.col3 = DEFAULT, ...
^
INSERT INTO test_upsert_001.t05 VALUES(DEFAULT, DEFAULT, 200), (DEFAULT, 200, DEFAULT)
ON DUPLICATE KEY UPDATE t05.col3 = DEFAULT, t05.col1 = test_upsert_001.t05.col3 + 1;
SET CURRENT_SCHEMA TO test_upsert_001;
DROP USER upsert_tester CASCADE;
DROP SCHEMA test_upsert_001 CASCADE;
NOTICE: drop cascades to 6 other objects
DETAIL: drop cascades to table t00
drop cascades to table t01
drop cascades to table t02
drop cascades to table t03
drop cascades to table t04
drop cascades to table t05

View File

@ -0,0 +1,545 @@
DROP SCHEMA test_upsert_002 CASCADE;
ERROR: schema "test_upsert_002" does not exist
CREATE SCHEMA test_upsert_002;
SET CURRENT_SCHEMA TO test_upsert_002;
-- enable_upsert_to_merge must is off, or upsert will be translated to merge.
SET enable_upsert_to_merge TO OFF;
-- test t1 with no index
CREATE TABLE t1 (
col1 INT,
col2 INT,
col3 INT DEFAULT 1,
-- col4 TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
col5 BIGSERIAL
) ;
NOTICE: CREATE TABLE will create implicit sequence "t1_col5_seq" for serial column "t1.col5"
INSERT INTO t1 VALUES (1, 2) ON DUPLICATE KEY UPDATE col1 = 3;
--- should always insert
INSERT INTO t1 VALUES (1, 2) ON DUPLICATE KEY UPDATE col2 = 3;
INSERT INTO t1 VALUES (1, 2) ON DUPLICATE KEY UPDATE t1.col2 = 4;
--- appoint column list in insert clause, should always insert
INSERT INTO t1(col1, col3) VALUES (1, 3) ON DUPLICATE KEY UPDATE col2 = 5;
INSERT INTO t1(col1, col3) VALUES (1, 3) ON DUPLICATE KEY UPDATE t1.col2 = 6;
--- multiple rows, should always insert
INSERT INTO t1 VALUES (2, 1), (2, 1) ON DUPLICATE KEY UPDATE col2 = 7, col3 = 7;
SELECT * FROM t1 ORDER BY col5;
col1 | col2 | col3 | col5
------+------+------+------
1 | 2 | 1 | 1
1 | 2 | 1 | 2
1 | 2 | 1 | 3
1 | | 3 | 4
1 | | 3 | 5
2 | 1 | 1 | 6
2 | 1 | 1 | 7
(7 rows)
--- test union, should insert
INSERT INTO t1 (col1, col2)
SELECT * FROM
(SELECT col1, col2 FROM t1
UNION
SELECT col1, col3 FROM t1) AS union_table
ON DUPLICATE KEY UPDATE col3 = (col1 + col2 + col3) * 10;
SELECT col1, col2, col3 FROM t1 WHERE col5 > 6 ORDER BY col1, col2;
col1 | col2 | col3
------+------+------
1 | 1 | 1
1 | 2 | 1
1 | 3 | 1
1 | | 1
2 | 1 | 1
2 | 1 | 1
(6 rows)
--- test subquery, should insert
INSERT INTO t1
(SELECT col1 || col2 || '00' FROM t1 ORDER BY col5)
ON DUPLICATE KEY UPDATE col3 = col1 * 100;
SELECT col1, col2, col3 FROM t1 WHERE col1 >= 100 ORDER BY col1;
col1 | col2 | col3
------+------+------
100 | | 1
100 | | 1
100 | | 1
1100 | | 1
1200 | | 1
1200 | | 1
1200 | | 1
1200 | | 1
1300 | | 1
2100 | | 1
2100 | | 1
2100 | | 1
(12 rows)
-- test t2 with one primary key
CREATE TABLE t2 (
col1 INT,
col2 INT PRIMARY KEY,
col3 INT DEFAULT 1,
col4 TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
col5 BIGSERIAL
) ;
NOTICE: CREATE TABLE will create implicit sequence "t2_col5_seq" for serial column "t2.col5"
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "t2_pkey" for table "t2"
--- primary key or unique key are not allowed to update
INSERT INTO t2 VALUES (1, 1) ON DUPLICATE KEY UPDATE col2 = 3;
ERROR: INSERT ON DUPLICATE KEY UPDATE don't allow update on primary key or unique key.
INSERT INTO t2 VALUES (1, 1) ON DUPLICATE KEY UPDATE t2.col2 = 3;
ERROR: INSERT ON DUPLICATE KEY UPDATE don't allow update on primary key or unique key.
INSERT INTO t2 (col2, col3, col4, col5)
VALUES (10, 10, CURRENT_TIMESTAMP(0), 10),
(20, 20, CURRENT_TIMESTAMP(1), 20),
(30, 30, CURRENT_TIMESTAMP(2), 30)
ON DUPLICATE KEY UPDATE
col1 = 100,
col2 = 100,
col3 = 100,
col4 = '2019-08-09'::TIMESTAMP,
col5 = 100;
ERROR: INSERT ON DUPLICATE KEY UPDATE don't allow update on primary key or unique key.
--- should insert
INSERT INTO t2 VALUES (1, 1) ON DUPLICATE KEY UPDATE col1 = 30;
INSERT INTO t2 VALUES (2, 2) ON DUPLICATE KEY UPDATE t2.col1 = 40;
INSERT INTO t2 VALUES (3, 3) ON DUPLICATE KEY UPDATE col1 = col1 * 2;
INSERT INTO t2 VALUES (4, 4) ON DUPLICATE KEY UPDATE t2.col1 = t2.col1 * 2 ;
INSERT INTO t2 VALUES (5, 5) ON DUPLICATE KEY UPDATE col1 = col2 + 1;
INSERT INTO t2 VALUES (6, 6) ON DUPLICATE KEY UPDATE t2.col1 = t2.col2 + 1;
INSERT INTO t2 VALUES (7, 7) ON DUPLICATE KEY UPDATE col1 = extract(dow from col4) + 10;
INSERT INTO t2 VALUES (8, 8) ON DUPLICATE KEY UPDATE t2.col1 = extract(century from col4) * 100 + extract(isodow from col4);
SELECT col1, col2, col3, col5 FROM t2 ORDER BY col5;
col1 | col2 | col3 | col5
------+------+------+------
1 | 1 | 1 | 1
2 | 2 | 1 | 2
3 | 3 | 1 | 3
4 | 4 | 1 | 4
5 | 5 | 1 | 5
6 | 6 | 1 | 6
7 | 7 | 1 | 7
8 | 8 | 1 | 8
(8 rows)
--- should update
INSERT INTO t2 VALUES (3, 1) ON DUPLICATE KEY UPDATE col1 = 30, col3 = col5 + 1;
INSERT INTO t2 VALUES (4, 2) ON DUPLICATE KEY UPDATE t2.col1 = 40, t2.col3 = t2.col5;
INSERT INTO t2 VALUES (3, 3), (4, 4) ON DUPLICATE KEY UPDATE col3 = t2.col5 + 1;
INSERT INTO t2 VALUES (5, 5) ON DUPLICATE KEY UPDATE col1 = extract(dow from col4) + 10;
INSERT INTO t2 VALUES (6, 6) ON DUPLICATE KEY UPDATE t2.col1 = extract(century from col4) * 100 + extract(isodow from col4);
SELECT col1, col2, col3, col5 FROM t2 ORDER BY col5;
col1 | col2 | col3 | col5
------+------+------+------
30 | 1 | 2 | 1
40 | 2 | 2 | 2
3 | 3 | 4 | 3
4 | 4 | 5 | 4
--?.*| 5 | 1 | 5
--?.*| 6 | 1 | 6
7 | 7 | 1 | 7
8 | 8 | 1 | 8
(8 rows)
-- primary key are not allowed to be null
INSERT INTO t2 (col1) VALUES (10) ON DUPLICATE KEY UPDATE col1 = 10;
ERROR: null value in column "col2" violates not-null constraint
--?
--- appoint column list in insert clause
---- should insert
INSERT INTO t2 (col2, col3) VALUES (9, 9) ON DUPLICATE KEY UPDATE col1 = 90;
INSERT INTO t2 (col2, col3, col4, col5)
VALUES (10, 10, CURRENT_TIMESTAMP(0), 10),
(20, 20, CURRENT_TIMESTAMP(1), 20),
(30, 30, CURRENT_TIMESTAMP(2), 30)
ON DUPLICATE KEY UPDATE
col1 = 100,
col3 = 100,
col4 = '2019-08-20'::TIMESTAMP,
col5 = 100;
SELECT * FROM t2 ORDER BY col5;
col1 | col2 | col3 | col4 | col5
------+------+------+---------------------------------+------
--? 30 | 1 | 2 | .* | 1
--? 40 | 2 | 2 | .* | 2
--? 3 | 3 | 4 | .* | 3
--? 4 | 4 | 5 | .* | 4
--? .* | 5 | 1 | .* | 5
--? .* | 6 | 1 | .* | 6
--? 7 | 7 | 1 | .* | 7
--? 8 | 8 | 1 | .* | 8
--? | 10 | 10 | .* | 10
--? | 9 | 9 | .* | 16
--? | 20 | 20 | .* | 20
--? | 30 | 30 | .* | 30
(12 rows)
---- should update
INSERT INTO t2 (col2, col3) VALUES (9, 9) ON DUPLICATE KEY UPDATE col1 = 90;
INSERT INTO t2 (col2, col3, col4, col5)
VALUES (10, 10, CURRENT_TIMESTAMP(0), 10),
(20, 20, CURRENT_TIMESTAMP(1), 20),
(30, 30, CURRENT_TIMESTAMP(2), 30)
ON DUPLICATE KEY UPDATE
col1 = 100,
col3 = 100,
col4 = '2019-08-20'::TIMESTAMP,
col5 = 100;
SELECT * FROM t2 ORDER BY col5, col2;
col1 | col2 | col3 | col4 | col5
------+------+------+---------------------------------+------
--? 30 | 1 | 2 | .* | 1
--? 40 | 2 | 2 | .* | 2
--? 3 | 3 | 4 | .* | 3
--? 4 | 4 | 5 | .* | 4
--? .* | 5 | 1 | .* | 5
--? .* | 6 | 1 | .* | 6
--? 7 | 7 | 1 | .* | 7
--? 8 | 8 | 1 | .* | 8
--? 90 | 9 | 9 | .* | 16
100 | 10 | 100 | Tue Aug 20 00:00:00 2019 | 100
100 | 20 | 100 | Tue Aug 20 00:00:00 2019 | 100
100 | 30 | 100 | Tue Aug 20 00:00:00 2019 | 100
(12 rows)
--- test subquery
---- should insert
INSERT INTO t2
(SELECT col1 * 1000, col2 * 1000 + 1 FROM t2 ORDER BY col5 LIMIT 2)
ON DUPLICATE KEY UPDATE col3 = col2 + 1;
INSERT INTO t2 (col2, col3)
(SELECT col1 * 1000 + 2, col2 * 1000 FROM t2 ORDER BY col5 LIMIT 2 OFFSET 1)
ON DUPLICATE KEY UPDATE col3 = col2 + 1;
SELECT col1, col2, col3, col5 FROM t2 ORDER BY col5, col2;
col1 | col2 | col3 | col5
-------+-------+------+------
30 | 1 | 2 | 1
40 | 2 | 2 | 2
3 | 3 | 4 | 3
4 | 4 | 5 | 4
--? .* | 5 | 1 | 5
--? .* | 6 | 1 | 6
7 | 7 | 1 | 7
8 | 8 | 1 | 8
90 | 9 | 9 | 16
--? 30000 | 1001 | 1 | 11
--? 40000 | 2001 | 1 | 12
--? | 40002 | 2000 | 13
--? | 3002 | 3000 | 14
100 | 10 | 100 | 100
100 | 20 | 100 | 100
100 | 30 | 100 | 100
(16 rows)
---- should update
INSERT INTO t2
(SELECT col1 * 1000, col2 * 1000 + 1 FROM t2 ORDER BY col5 LIMIT 2)
ON DUPLICATE KEY UPDATE col3 = col2 + 1;
INSERT INTO t2 (col2, col3)
(SELECT col1 * 1000 + 2, col2 * 1000 FROM t2 ORDER BY col5 LIMIT 2 OFFSET 1)
ON DUPLICATE KEY UPDATE col3 = col2 + 1;
SELECT col1, col2, col3, col5 FROM t2 ORDER BY col5, col2;
col1 | col2 | col3 | col5
-------+-------+-------+------
30 | 1 | 2 | 1
40 | 2 | 2 | 2
3 | 3 | 4 | 3
4 | 4 | 5 | 4
--? .* | 5 | 1 | 5
--? .* | 6 | 1 | 6
7 | 7 | 1 | 7
8 | 8 | 1 | 8
90 | 9 | 9 | 16
--? 30000 | 1001 | 1002 | 11
--? 40000 | 2001 | 2002 | 12
--? | 40002 | 40003 | 13
--? | 3002 | 3003 | 14
100 | 10 | 100 | 100
100 | 20 | 100 | 100
100 | 30 | 100 | 100
(16 rows)
--- test union, some insert some update
SELECT col1, col2 FROM t1 WHERE col2 IS NOT NULL
UNION
SELECT col1, col3 FROM t1 ORDER BY 1, 2;
col1 | col2
------+------
1 | 1
1 | 2
1 | 3
2 | 1
100 | 1
1100 | 1
1200 | 1
1300 | 1
2100 | 1
(9 rows)
INSERT INTO t2 (col1, col2)
SELECT * FROM
(SELECT col1, col2 FROM t1 WHERE col2 IS NOT NULL
UNION
SELECT col1, col3 FROM t1) AS union_table
ON DUPLICATE KEY UPDATE col3 = (col1 + col2 + col3);
SELECT col1, col2, col3, col5 FROM t2 ORDER BY col5, col2;
col1 | col2 | col3 | col5
-------+-------+-------+------
30 | 1 | 219 | 1
40 | 2 | 44 | 2
3 | 3 | 10 | 3
4 | 4 | 5 | 4
--? .* | 5 | 1 | 5
--? .* | 6 | 1 | 6
7 | 7 | 1 | 7
8 | 8 | 1 | 8
90 | 9 | 9 | 16
--? 30000 | 1001 | 1002 | 11
--? 40000 | 2001 | 2002 | 12
--? | 40002 | 40003 | 13
--? | 3002 | 3003 | 14
100 | 10 | 100 | 100
100 | 20 | 100 | 100
100 | 30 | 100 | 100
(16 rows)
INSERT INTO t2 (col1, col2)
SELECT col1, col2 FROM t1 WHERE col2 IS NOT NULL
UNION
SELECT col1, col3 FROM t1
ON DUPLICATE KEY UPDATE col3 = col3 + 1;
SELECT col1, col2, col3, col5 FROM t2 ORDER BY col5, col2;
col1 | col2 | col3 | col5
-------+-------+-------+------
30 | 1 | 226 | 1
40 | 2 | 45 | 2
3 | 3 | 11 | 3
4 | 4 | 5 | 4
--? 15 | 5 | 1 | 5
--? 2105 | 6 | 1 | 6
7 | 7 | 1 | 7
8 | 8 | 1 | 8
90 | 9 | 9 | 16
--? 30000 | 1001 | 1002 | 11
--? 40000 | 2001 | 2002 | 12
--? | 40002 | 40003 | 13
--? | 3002 | 3003 | 14
100 | 10 | 100 | 100
100 | 20 | 100 | 100
100 | 30 | 100 | 100
(16 rows)
reset behavior_compat_options;
-- test INTERSECT, should update
(SELECT col1, col1 + col2 FROM t1 WHERE col2 IS NOT NULL
UNION
SELECT 1, 2)
INTERSECT
SELECT col1, col3 FROM t1;
col1 | ?column?
------+----------
1 | 3
(1 row)
INSERT INTO t2 (col1, col2)
(SELECT col1, col1 + col2 FROM t1 WHERE col2 IS NOT NULL
UNION
SELECT 1, 2)
INTERSECT
SELECT col1, col3 FROM t1
ON DUPLICATE KEY UPDATE col3 = col3 + 1;
SELECT col1, col2, col3, col5 FROM t2 WHERE col2 = 3 ORDER BY col5, col2;
col1 | col2 | col3 | col5
------+------+------+------
3 | 3 | 12 | 3
(1 row)
-- test EXCEPT, should update
SELECT col1, col2 FROM t1 WHERE col2 IS NOT NULL
EXCEPT
(SELECT col1, col3 FROM t1
UNION
SELECT NULL, NULL);
col1 | col2
------+------
1 | 2
(1 row)
INSERT INTO t2 (col1, col2)
SELECT col1, col2 FROM t1 WHERE col2 IS NOT NULL
EXCEPT
(SELECT col1, col3 FROM t1
UNION
SELECT NULL, NULL)
ON DUPLICATE KEY UPDATE col3 = col3 + 1;
SELECT col1, col2, col3, col5 FROM t2 WHERE col2 = 2 ORDER BY col5, col2;
col1 | col2 | col3 | col5
------+------+------+------
40 | 2 | 46 | 2
(1 row)
-- test unique index with not default value
ALTER TABLE t2 DROP CONSTRAINT t2_pkey;
CREATE UNIQUE INDEX t2_u_index ON t2(col2, col5);
SELECT col1, col2 FROM t1 WHERE col2 IS NOT NULL
EXCEPT
(SELECT col1, col3 FROM t1
UNION
SELECT NULL, NULL);
col1 | col2
------+------
1 | 2
(1 row)
INSERT INTO t2
SELECT col1, col2 FROM t1 WHERE col2 IS NOT NULL
EXCEPT
(SELECT col1, col3 FROM t1
UNION
SELECT NULL, NULL)
ON DUPLICATE KEY UPDATE col3 = col3 + 1;
SELECT col1, col2, col3, col5 FROM t2 WHERE col2 = 2 ORDER BY col5, col2;
col1 | col2 | col3 | col5
------+------+------+------
40 | 2 | 46 | 2
1 | 2 | 1 | 46
(2 rows)
-- test t3 with one primary index with two columns
CREATE TABLE t3 (
col1 INT,
col2 INT,
col3 INT DEFAULT 1,
-- col4 TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
col5 BIGSERIAL,
PRIMARY KEY (col2, col3)
) ;
NOTICE: CREATE TABLE will create implicit sequence "t3_col5_seq" for serial column "t3.col5"
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "t3_pkey" for table "t3"
--- column referenced by primary key are not allowed to update
INSERT INTO t3 VALUES (1, 1) ON DUPLICATE KEY UPDATE col3 = 3;
ERROR: INSERT ON DUPLICATE KEY UPDATE don't allow update on primary key or unique key.
--- should insert when not contains primary key and not all primary key referred columns have default value.
--- but will fail cause primary key should not be null
INSERT INTO t3 (col1) VALUES (1) ON DUPLICATE KEY UPDATE col1 = 2;
ERROR: null value in column "col2" violates not-null constraint
--?.*
--- should insert
--- (SEQUENCE BUG: the serial column will starts from 2 since the above statement has applied for a sequence)
INSERT INTO t3 VALUES (1, 1) ON DUPLICATE KEY UPDATE col1 = 10;
INSERT INTO t3 VALUES (2, 2, 2) ON DUPLICATE KEY UPDATE col5 = 20;
SELECT * FROM t3 order by col5;
col1 | col2 | col3 | col5
------+------+------+------
1 | 1 | 1 | 2
2 | 2 | 2 | 3
(2 rows)
--- should update
INSERT INTO t3 VALUES (1, 1) ON DUPLICATE KEY UPDATE col1 = 10;
INSERT INTO t3 VALUES (2, 2, 2) ON DUPLICATE KEY UPDATE col5 = 20;
SELECT * FROM t3 order by col5;
col1 | col2 | col3 | col5
------+------+------+------
10 | 1 | 1 | 2
2 | 2 | 2 | 20
(2 rows)
--- test subquery
---- should insert
INSERT INTO t3 (col2, col3) (SELECT max(col2) + 1, max(col3) + 1 FROM t3) ON DUPLICATE KEY UPDATE col1 = col2 + col3;
SELECT * FROM t3 order by col5;
col1 | col2 | col3 | col5
------+------+------+------
10 | 1 | 1 | 2
| 3 | 3 | 6
2 | 2 | 2 | 20
(3 rows)
---- should update
INSERT INTO t3 (col2, col3) (SELECT max(col2), max(col3) FROM t3) ON DUPLICATE KEY UPDATE col1 = col2 + col3;
SELECT * FROM t3 order by col5;
col1 | col2 | col3 | col5
------+------+------+------
10 | 1 | 1 | 2
6 | 3 | 3 | 6
2 | 2 | 2 | 20
(3 rows)
-- test t3 with one unique index with two columns
TRUNCATE t3;
ALTER TABLE t3 DROP CONSTRAINT t3_pkey;
ALTER TABLE t3 ALTER COLUMN col2 DROP NOT NULL;
CREATE UNIQUE INDEX t3_ukey ON t3 (col2, col3);
--- column referenced by unique key are not allowed to update
INSERT INTO t3 VALUES (1, 1) ON DUPLICATE KEY UPDATE col3 = 3;
ERROR: INSERT ON DUPLICATE KEY UPDATE don't allow update on primary key or unique key.
--- should insert cause not contains unique key and not all unique key referred columns have default value.
INSERT INTO t3 (col1) VALUES (1) ON DUPLICATE KEY UPDATE col1 = 2;
INSERT INTO t3 (col1) VALUES (1) ON DUPLICATE KEY UPDATE col1 = 2;
SELECT * FROM t3 order by col5;
col1 | col2 | col3 | col5
------+------+------+------
1 | | 1 | 8
1 | | 1 | 9
(2 rows)
--- should insert
INSERT INTO t3 VALUES (1, 1) ON DUPLICATE KEY UPDATE col1 = 10;
INSERT INTO t3 VALUES (2, 2, 2) ON DUPLICATE KEY UPDATE t3.col5 = 20;
SELECT * FROM t3 ORDER BY col5;
col1 | col2 | col3 | col5
------+------+------+------
1 | | 1 | 8
1 | | 1 | 9
1 | 1 | 1 | 10
2 | 2 | 2 | 11
(4 rows)
--- should update
INSERT INTO t3 VALUES (1, 1) ON DUPLICATE KEY UPDATE t3.col1 = 10;
INSERT INTO t3 VALUES (2, 2, 2) ON DUPLICATE KEY UPDATE col5 = 20;
SELECT * FROM t3 ORDER BY col5;
col1 | col2 | col3 | col5
------+------+------+------
1 | | 1 | 8
1 | | 1 | 9
10 | 1 | 1 | 10
2 | 2 | 2 | 20
(4 rows)
--- test subquery
---- should insert
INSERT INTO t3 (SELECT 100, NULL, max(col3) FROM t3) ON DUPLICATE KEY UPDATE col1 = col2 + col3;
INSERT INTO t3 (SELECT 100, NULL, max(col3) FROM t3) ON DUPLICATE KEY UPDATE col1 = col2 + col3;
INSERT INTO t3 (col2, col3) (SELECT max(col2) + 1, max(col3) + 1 FROM t3) ON DUPLICATE KEY UPDATE col1 = col2 + col3;
SELECT * FROM t3 ORDER BY col5;
col1 | col2 | col3 | col5
------+------+------+------
1 | | 1 | 8
1 | | 1 | 9
10 | 1 | 1 | 10
100 | | 2 | 14
100 | | 2 | 15
| 3 | 3 | 16
2 | 2 | 2 | 20
(7 rows)
---- should update
INSERT INTO t3 (col2, col3) (SELECT max(col2), max(col3) FROM t3) ON DUPLICATE KEY UPDATE col1 = col2 + col3;
SELECT * FROM t3 ORDER BY col5;
col1 | col2 | col3 | col5
------+------+------+------
1 | | 1 | 8
1 | | 1 | 9
10 | 1 | 1 | 10
100 | | 2 | 14
100 | | 2 | 15
6 | 3 | 3 | 16
2 | 2 | 2 | 20
(7 rows)
DROP SCHEMA test_upsert_002 CASCADE;
NOTICE: drop cascades to 3 other objects
DETAIL: drop cascades to table t1
drop cascades to table t2
drop cascades to table t3

View File

@ -0,0 +1,313 @@
DROP SCHEMA test_insert_update_003 CASCADE;
ERROR: schema "test_insert_update_003" does not exist
CREATE SCHEMA test_insert_update_003;
SET CURRENT_SCHEMA TO test_insert_update_003;
-- enable_upsert_to_merge must is off, or upsert will be translated to merge.
SET enable_upsert_to_merge TO OFF;
-- test t4 with one primary key with three columns
CREATE TABLE t4 (
col1 INT,
col2 INT DEFAULT 0,
col3 INT DEFAULT 1,
col4 TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
col5 BIGSERIAL,
PRIMARY KEY (col2, col3, col5)
) ;
NOTICE: CREATE TABLE will create implicit sequence "t4_col5_seq" for serial column "t4.col5"
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "t4_pkey" for table "t4"
--- should insert
INSERT INTO t4 VALUES (1) ON DUPLICATE KEY UPDATE col1 = 10;
INSERT INTO t4 VALUES (1) ON DUPLICATE KEY UPDATE col1 = 10;
INSERT INTO t4 VALUES (2, 2, 2) ON DUPLICATE KEY UPDATE col1 = 200;
INSERT INTO t4 VALUES (100, 100, 100, CURRENT_TIMESTAMP, 100) ON DUPLICATE KEY UPDATE col1 = 1000;
SELECT col1, col2, col3, col5 FROM t4 ORDER BY col5;
col1 | col2 | col3 | col5
------+------+------+------
1 | 0 | 1 | 1
1 | 0 | 1 | 2
2 | 2 | 2 | 3
100 | 100 | 100 | 100
(4 rows)
--- should update
INSERT INTO t4 VALUES (2, 2, 2, CURRENT_TIMESTAMP, 3) ON DUPLICATE KEY UPDATE col1 = 200;
INSERT INTO t4 VALUES (100, 100, 100, CURRENT_TIMESTAMP, 100) ON DUPLICATE KEY UPDATE col1 = 1000;
SELECT col1, col2, col3, col5 FROM t4 ORDER BY col5;
col1 | col2 | col3 | col5
------+------+------+------
1 | 0 | 1 | 1
1 | 0 | 1 | 2
200 | 2 | 2 | 3
1000 | 100 | 100 | 100
(4 rows)
--- error: duplicate key update on (x, x, 20)
--- this is because current version is not inplace update but merge,
--- so when the subquery contains multiple same values, it will cause duplicate insert failure.
SELECT col3, sum(col3) * 10 FROM t4 GROUP BY col3 ORDER BY 1, 2;
col3 | ?column?
------+----------
1 | 20
2 | 20
100 | 1000
(3 rows)
INSERT INTO t4 (col1, col5)
(SELECT col3, sum(col3) * 10 FROM t4 GROUP BY col3)
ON DUPLICATE KEY UPDATE col1 = 3;
-- test t5 with sequence or default column with volatile function in constaint index
CREATE TABLE t5 (
col1 INT,
col2 INT DEFAULT 1,
col3 BIGSERIAL,
-- col4 TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
col5 INTEGER(10, 5) DEFAULT RANDOM() + 1
) ;
NOTICE: CREATE TABLE will create implicit sequence "t5_col3_seq" for serial column "t5.col3"
-- test t5 with sequence column in constaint index
CREATE UNIQUE INDEX u_t5_index1 ON t5(col1, col3);
--- should insert
INSERT INTO t5 VALUES (1), (1), (1) ON DUPLICATE KEY UPDATE col2 = col3;
INSERT INTO t5 DEFAULT VALUES ON DUPLICATE KEY UPDATE col2 = col3;
SELECT * FROM t5 ORDER BY col3;
col1 | col2 | col3 | col5
------+------+------+---------
--? 1 | 1 | 1 | 1.58182
--? 1 | 1 | 2 | 1.00814
--? 1 | 1 | 3 | 1.50194
--? | 1 | 4 | 1.12955
(4 rows)
--- should update
INSERT INTO t5 (col1, col3) VALUES (1, 1), (1, 2), (1, 3) ON DUPLICATE KEY UPDATE col5 = col2, col2 = col3 * 10;
SELECT * FROM t5 WHERE col1 = 1 ORDER BY col3;
col1 | col2 | col3 | col5
------+------+------+---------
1 | 10 | 1 | 1.00000
1 | 20 | 2 | 1.00000
1 | 30 | 3 | 1.00000
(3 rows)
--- should some insert some update
INSERT INTO t5 (col1, col3) VALUES (2, 5), (2, 6);
SELECT col1, col2, col3 FROM t5 ORDER BY col3;
col1 | col2 | col3
------+------+------
1 | 10 | 1
1 | 20 | 2
1 | 30 | 3
| 1 | 4
2 | 1 | 5
2 | 1 | 6
(6 rows)
INSERT INTO t5 (col1) VALUES (2), (2), (2) ON DUPLICATE KEY UPDATE col2 = col3;
SELECT col1, col2, col3 FROM t5 ORDER BY col3;
col1 | col2 | col3
------+------+------
1 | 10 | 1
1 | 20 | 2
1 | 30 | 3
| 1 | 4
2 | 5 | 5
2 | 6 | 6
2 | 1 | 7
(7 rows)
--- should INSERT and sequence starting from 7
INSERT INTO t5 VALUES (2), (2);
SELECT col1, col2, col3 FROM t5 ORDER BY col3;
col1 | col2 | col3
------+------+------
1 | 10 | 1
1 | 20 | 2
1 | 30 | 3
| 1 | 4
2 | 5 | 5
2 | 6 | 6
2 | 1 | 7
2 | 1 | 8
2 | 1 | 9
(9 rows)
-- test with volatile function as default column in constraint index
TRUNCATE t5;
DROP INDEX u_t5_index1;
CREATE UNIQUE INDEX u_t5_index2 ON t5(col1, col5) WHERE col1 > 2;
--- should insert
INSERT INTO t5 VALUES (3), (3), (3) ON DUPLICATE KEY UPDATE col2 = col3;
INSERT INTO t5 (col1) VALUES (4), (4), (4) ON DUPLICATE KEY UPDATE col2 = col3;
SELECT * FROM t5 ORDER BY col3;
col1 | col2 | col3 | col5
------+------+------+---------
--? 3 | 1 | 10 | 1.24521
--? 3 | 1 | 11 | 1.80598
--? 3 | 1 | 12 | 1.86845
--? 4 | 1 | 13 | 1.65797
--? 4 | 1 | 14 | 1.07881
--? 4 | 1 | 15 | 1.69493
(6 rows)
--- should update
INSERT INTO t5 (col1, col5) SELECT col1, col5 FROM t5 where col1 = 3 ON DUPLICATE KEY UPDATE col2 = col5 * 100;
SELECT * FROM t5 ORDER BY col3;
col1 | col2 | col3 | col5
------+------+------+---------
--? 3 | 125 | 10 | 1.24521
--? 3 | 181 | 11 | 1.80598
--? 3 | 187 | 12 | 1.86845
--? 4 | 1 | 13 | 1.65797
--? 4 | 1 | 14 | 1.07881
--? 4 | 1 | 15 | 1.69493
(6 rows)
--- test subquery
---- should insert
INSERT INTO t5 (col1, col2) SELECT col1, col2 FROM t5 ON DUPLICATE KEY UPDATE col2 = col5 * 100;
SELECT * FROM t5 ORDER BY col3;
col1 | col2 | col3 | col5
------+------+------+---------
--? 3 | 167 | 10 | 1.67400
--? 3 | 132 | 11 | 1.31552
--? 3 | 129 | 12 | 1.29423
--? 4 | 1 | 13 | 1.44100
--? 4 | 1 | 14 | 1.37620
--? 4 | 1 | 15 | 1.51296
--? 4 | 1 | 16 | 1.37516
--? 4 | 1 | 17 | 1.21710
--? 4 | 1 | 18 | 1.50422
--? 3 | 132 | 19 | 1.30560
--? 3 | 167 | 20 | 1.62282
--? 3 | 129 | 21 | 1.76699
(12 rows)
---- should update
INSERT INTO t5 SELECT * FROM t5 ON DUPLICATE KEY UPDATE col2 = col5 * 1000;
SELECT * FROM t5 ORDER BY col3;
col1 | col2 | col3 | col5
------+------+------+---------
--? 3 | 1674 | 10 | 1.67400
--? 3 | 1316 | 11 | 1.31552
--? 3 | 1294 | 12 | 1.29423
--? 4 | 1441 | 13 | 1.44100
--? 4 | 1376 | 14 | 1.37620
--? 4 | 1513 | 15 | 1.51296
--? 4 | 1375 | 16 | 1.37516
--? 4 | 1217 | 17 | 1.21710
--? 4 | 1504 | 18 | 1.50422
--? 3 | 1306 | 19 | 1.30560
--? 3 | 1623 | 20 | 1.62282
--? 3 | 1767 | 21 | 1.76699
(12 rows)
-- test t6 with one more index
CREATE TABLE t6 (
col1 INT,
col2 INT DEFAULT 1,
col3 BIGSERIAL,
-- col4 TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
col5 INTEGER(10, 5) DEFAULT RANDOM(),
col6 INT,
col7 TEXT
) ;
NOTICE: CREATE TABLE will create implicit sequence "t6_col3_seq" for serial column "t6.col3"
ALTER TABLE t6 ADD PRIMARY KEY (col1, col3);
NOTICE: ALTER TABLE / ADD PRIMARY KEY will create implicit index "t6_pkey" for table "t6"
CREATE UNIQUE INDEX u_t6_index1 ON t6(col1, col5, col6);
INSERT INTO t6 (col1) VALUES (1), (2), (3), (4), (5);
SELECT col1, col2, col3, col6, col7 FROM t6 ORDER BY col3;
col1 | col2 | col3 | col6 | col7
------+------+------+------+------
1 | 1 | 1 | |
2 | 1 | 2 | |
3 | 1 | 3 | |
4 | 1 | 4 | |
5 | 1 | 5 | |
(5 rows)
--- should not insert
INSERT INTO t6 (col1) VALUES (1), (2), (3), (4), (5) ON DUPLICATE KEY UPDATE col6 = power(col1, col2);
ERROR: INSERT ON DUPLICATE KEY UPDATE don't allow update on primary key or unique key.
SELECT col1, col2, col3, col6, col7 FROM t6 ORDER BY col3;
col1 | col2 | col3 | col6 | col7
------+------+------+------+------
1 | 1 | 1 | |
2 | 1 | 2 | |
3 | 1 | 3 | |
4 | 1 | 4 | |
5 | 1 | 5 | |
(5 rows)
--- should update because primary key matches
INSERT INTO t6 (col1, col3) VALUES (6, 11), (6, 12);
SELECT col1, col2, col3, col6, col7 FROM t6 WHERE col1 = 6 ORDER BY col3;
col1 | col2 | col3 | col6 | col7
------+------+------+------+------
6 | 1 | 11 | |
6 | 1 | 12 | |
(2 rows)
INSERT INTO t6 (col1) VALUES (6), (6), (6) ON DUPLICATE KEY UPDATE col2 = col1 + col3, col6 = col2 * 10;
ERROR: INSERT ON DUPLICATE KEY UPDATE don't allow update on primary key or unique key.
SELECT col1, col2, col3, col6, col7 FROM t6 WHERE col1 = 6 ORDER BY col3;
col1 | col2 | col3 | col6 | col7
------+------+------+------+------
6 | 1 | 11 | |
6 | 1 | 12 | |
(2 rows)
--- should update for those col6 is not null bacause they will match the unique index,
--- and insert for those col6 is null because the unique index containing null never matches,
--- also primary key will not match
--- be ware the sequence column of the inserted row will jump n step, where n is the count of the not null rows,
--- because those sequence have to be generated during the unique index join stage.
INSERT INTO t6 (col1, col5, col6)
(SELECT col1, col5, col6 FROM t6 WHERE col1 = 6)
ON DUPLICATE KEY UPDATE
col7 = col2 + 1;
SELECT col1, col2, col3, col6, col7 FROM t6 WHERE col1 = 6 ORDER BY col1, col3, col6, col7;
col1 | col2 | col3 | col6 | col7
------+------+------+------+------
6 | 1 | 6 | |
6 | 1 | 7 | |
6 | 1 | 11 | |
6 | 1 | 12 | |
(4 rows)
--- should update because unique index and primary key both match
INSERT INTO t6 (col1, col3, col5, col6)
(SELECT col1, col3, col5, col6 FROM t6 WHERE col1 = 6 AND col6 IS NOT NULL)
ON DUPLICATE KEY UPDATE
col7 = col7 * 10;
SELECT col1, col2, col3, col6, col7 FROM t6 WHERE col1 = 6 ORDER BY col1, col3, col6, col7;
col1 | col2 | col3 | col6 | col7
------+------+------+------+------
6 | 1 | 6 | |
6 | 1 | 7 | |
6 | 1 | 11 | |
6 | 1 | 12 | |
(4 rows)
--- insert when col3 = 17 because constaints does not match,
--- but update when col3 = 18 because 18 has been inserted and will cause a match
INSERT INTO t6 (col1, col3, col5, col6) VALUES (7, 18, 100, 100);
SELECT * FROM t6 WHERE col3 > 16 ORDER BY col1, col3, col6, col7;
col1 | col2 | col3 | col5 | col6 | col7
------+------+------+-----------+------+------
7 | 1 | 18 | 100.00000 | 100 |
(1 row)
INSERT INTO t6 (col1, col5, col6) VALUES (7, 10, 10), (7, 100, 100) ON DUPLICATE KEY UPDATE
col7 = col3 * 100;
SELECT * FROM t6 WHERE col1 = 7 ORDER BY col1, col3, col6, col7;
col1 | col2 | col3 | col5 | col6 | col7
------+------+------+-----------+------+------
7 | 1 | 8 | 10.00000 | 10 |
7 | 1 | 18 | 100.00000 | 100 | 1800
(2 rows)
DROP SCHEMA test_insert_update_003 CASCADE;
NOTICE: drop cascades to 3 other objects
DETAIL: drop cascades to table t4
drop cascades to table t5
drop cascades to table t6

View File

@ -0,0 +1,466 @@
--
-- INSERT UPDATE, test explain command, comes from merge_explain and merge_explain_pretty
--
-- initial
CREATE SCHEMA test_insert_update_008;
SET current_schema = test_insert_update_008;
-- enable_upsert_to_merge must is off, or upsert will be translated to merge.
SET enable_upsert_to_merge TO OFF;
CREATE TABLE products_base
(
product_id INTEGER DEFAULT 0,
product_name VARCHAR(60) DEFAULT 'null',
category VARCHAR(60) DEFAULT 'unknown',
total INTEGER DEFAULT '0'
);
INSERT INTO products_base VALUES (1501, 'vivitar 35mm', 'electrncs', 100);
INSERT INTO products_base VALUES (1502, 'olympus is50', 'electrncs', 100);
INSERT INTO products_base VALUES (1600, 'play gym', 'toys', 100);
INSERT INTO products_base VALUES (1601, 'lamaze', 'toys', 100);
INSERT INTO products_base VALUES (1666, 'harry potter', 'dvd', 100);
CREATE TABLE newproducts_base
(
product_id INTEGER DEFAULT 0,
product_name VARCHAR(60) DEFAULT 'null',
category VARCHAR(60) DEFAULT 'unknown',
total INTEGER DEFAULT '0'
);
INSERT INTO newproducts_base VALUES (1502, 'olympus camera', 'electrncs', 200);
INSERT INTO newproducts_base VALUES (1601, 'lamaze', 'toys', 200);
INSERT INTO newproducts_base VALUES (1666, 'harry potter', 'toys', 200);
INSERT INTO newproducts_base VALUES (1700, 'wait interface', 'books', 200);
ANALYZE products_base;
ANALYZE newproducts_base;
--
-- row table
--
CREATE TABLE products_row
(
product_id INTEGER DEFAULT 0 PRIMARY KEY,
product_name VARCHAR(60) DEFAULT 'null',
category VARCHAR(60) DEFAULT 'unknown',
total INTEGER DEFAULT '0'
);
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "products_row_pkey" for table "products_row"
CREATE TABLE newproducts_row
(
product_id INTEGER DEFAULT 0 PRIMARY KEY,
product_name VARCHAR(60) DEFAULT 'null',
category VARCHAR(60) DEFAULT 'unknown',
total INTEGER DEFAULT '0'
);
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "newproducts_row_pkey" for table "newproducts_row"
INSERT INTO products_row SELECT * FROM products_base;
INSERT INTO newproducts_row SELECT * FROM newproducts_base;
ANALYZE products_row;
ANALYZE newproducts_row;
SET explain_perf_mode = normal;
-- explain verbose
EXPLAIN (VERBOSE on, COSTS off)
INSERT INTO products_row
SELECT product_id, product_name, category, total FROM newproducts_row
ON DUPLICATE KEY UPDATE
product_name = excluded.product_name,
category = excluded.category,
total = excluded.total;
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------
Insert on test_insert_update_008.products_row
Conflict Resolution: UPDATE
Conflict Arbiter Indexes: products_row_pkey
-> Seq Scan on test_insert_update_008.newproducts_row
Output: newproducts_row.product_id, newproducts_row.product_name, newproducts_row.category, newproducts_row.total
(5 rows)
EXPLAIN (VERBOSE on, COSTS off)
INSERT INTO products_row
SELECT newproducts_row.product_id,
newproducts_row.product_name,
newproducts_row.category,
newproducts_row.total
FROM newproducts_row, products_row
WHERE products_row.total + newproducts_row.total < 1000
ON DUPLICATE KEY UPDATE
product_name = excluded.product_name,
category = excluded.category,
total = excluded.total;
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Insert on test_insert_update_008.products_row
Conflict Resolution: UPDATE
Conflict Arbiter Indexes: products_row_pkey
-> Nested Loop
Output: newproducts_row.product_id, newproducts_row.product_name, newproducts_row.category, newproducts_row.total
Join Filter: ((test_insert_update_008.products_row.total + newproducts_row.total) < 1000)
-> Seq Scan on test_insert_update_008.products_row
Output: test_insert_update_008.products_row.product_id, test_insert_update_008.products_row.product_name, test_insert_update_008.products_row.category, test_insert_update_008.products_row.total
-> Materialize
Output: newproducts_row.product_id, newproducts_row.product_name, newproducts_row.category, newproducts_row.total
-> Seq Scan on test_insert_update_008.newproducts_row
Output: newproducts_row.product_id, newproducts_row.product_name, newproducts_row.category, newproducts_row.total
(12 rows)
EXPLAIN (VERBOSE on, COSTS off)
INSERT INTO products_row
SELECT product_id, product_name, category, total
FROM newproducts_row WHERE product_id IS NOT NULL AND product_name IS NOT NULL
ON DUPLICATE KEY UPDATE
product_name = excluded.product_name,
category = excluded.category,
total = excluded.total;
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------
Insert on test_insert_update_008.products_row
Conflict Resolution: UPDATE
Conflict Arbiter Indexes: products_row_pkey
-> Seq Scan on test_insert_update_008.newproducts_row
Output: newproducts_row.product_id, newproducts_row.product_name, newproducts_row.category, newproducts_row.total
Filter: ((newproducts_row.product_id IS NOT NULL) AND (newproducts_row.product_name IS NOT NULL))
(6 rows)
-- explain analyze
BEGIN;
EXPLAIN (ANALYZE on, COSTS off, TIMING off)
INSERT INTO products_row
SELECT product_id, product_name, category, total FROM newproducts_row
ON DUPLICATE KEY UPDATE
product_name = excluded.product_name,
category = excluded.category,
total = excluded.total;
QUERY PLAN
-----------------------------------------------------------
Insert on products_row (actual rows=4 loops=1)
Conflict Resolution: UPDATE
Conflict Arbiter Indexes: products_row_pkey
-> Seq Scan on newproducts_row (actual rows=4 loops=1)
--? Total runtime: .* ms
(5 rows)
ROLLBACK;
-- explain performance
\o insert_update_explain.txt
BEGIN;
EXPLAIN PERFORMANCE
INSERT INTO products_row
SELECT product_id, product_name, category, total FROM newproducts_row
ON DUPLICATE KEY UPDATE
product_name = excluded.product_name,
category = excluded.category,
total = excluded.total;
ROLLBACK;
\o
-- explain analyze
BEGIN;
EXPLAIN (ANALYZE on, COSTS off, TIMING off)
INSERT INTO products_row
SELECT product_id, product_name, category, total FROM newproducts_row
ON DUPLICATE KEY UPDATE
product_name = excluded.product_name,
category = excluded.category,
total = excluded.total;
QUERY PLAN
-----------------------------------------------------------
Insert on products_row (actual rows=4 loops=1)
Conflict Resolution: UPDATE
Conflict Arbiter Indexes: products_row_pkey
-> Seq Scan on newproducts_row (actual rows=4 loops=1)
--? Total runtime: .* ms
(5 rows)
ROLLBACK;
-- pretty mode performance
SET explain_perf_mode = pretty;
-- explain verbose
EXPLAIN (VERBOSE on, COSTS off)
INSERT INTO products_row
SELECT product_id, product_name, category, total FROM newproducts_row
ON DUPLICATE KEY UPDATE
product_name = excluded.product_name,
category = excluded.category,
total = excluded.total;
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------
Insert on test_insert_update_008.products_row
Conflict Resolution: UPDATE
Conflict Arbiter Indexes: products_row_pkey
-> Seq Scan on test_insert_update_008.newproducts_row
Output: newproducts_row.product_id, newproducts_row.product_name, newproducts_row.category, newproducts_row.total
(5 rows)
-- explain analyze
BEGIN;
EXPLAIN (ANALYZE on, COSTS off, TIMING off)
INSERT INTO products_row
SELECT product_id, product_name, category, total FROM newproducts_row
ON DUPLICATE KEY UPDATE
product_name = excluded.product_name,
category = excluded.category,
total = excluded.total;
QUERY PLAN
-----------------------------------------------------------
Insert on products_row (actual rows=4 loops=1)
Conflict Resolution: UPDATE
Conflict Arbiter Indexes: products_row_pkey
-> Seq Scan on newproducts_row (actual rows=4 loops=1)
--? Total runtime: .* ms
(5 rows)
ROLLBACK;
-- explain analyze
BEGIN;
EXPLAIN (ANALYZE on, COSTS off, TIMING off)
INSERT INTO products_row
SELECT product_id, product_name, category, total FROM newproducts_row
ON DUPLICATE KEY UPDATE
product_name = excluded.product_name,
category = excluded.category,
total = excluded.total;
QUERY PLAN
-----------------------------------------------------------
Insert on products_row (actual rows=4 loops=1)
Conflict Resolution: UPDATE
Conflict Arbiter Indexes: products_row_pkey
-> Seq Scan on newproducts_row (actual rows=4 loops=1)
--? Total runtime: .* ms
(5 rows)
ROLLBACK;
-- explain performance
\o insert_update_explain_pretty.txt
BEGIN;
EXPLAIN PERFORMANCE
INSERT INTO products_row
SELECT product_id, product_name, category, total FROM newproducts_row
ON DUPLICATE KEY UPDATE
product_name = excluded.product_name,
category = excluded.category,
total = excluded.total;
ROLLBACK;
SET explain_perf_mode = run;
BEGIN;
EXPLAIN PERFORMANCE
INSERT INTO products_row
SELECT product_id, product_name, category, total FROM newproducts_row
ON DUPLICATE KEY UPDATE
product_name = excluded.product_name,
category = excluded.category,
total = excluded.total;
ROLLBACK;
SET explain_perf_mode = summary;
BEGIN;
EXPLAIN PERFORMANCE
INSERT INTO products_row
SELECT product_id, product_name, category, total FROM newproducts_row
ON DUPLICATE KEY UPDATE
product_name = excluded.product_name,
category = excluded.category,
total = excluded.total;
ROLLBACK;
\o
CREATE TABLE item
(
a INT DEFAULT 3,
item_id NUMERIC(18,10),
item_name VARCHAR(100),
item_level NUMERIC(39,0),
item_desc VARCHAR(250),
item_subclass_cd VARCHAR(50),
item_type_cd VARCHAR(50),
inventory_ind CHAR(300),
vendor_party_id SMALLINT,
commodity_cd VARCHAR(50),
brand_cd VARCHAR(50),
item_available CHAR(100),
CONSTRAINT u_item_index UNIQUE (item_subclass_cd, vendor_party_id)
)
PARTITION BY RANGE (vendor_party_id)
(
PARTITION item_1 VALUES LESS THAN (0),
PARTITION item_2 VALUES LESS THAN (1),
PARTITION item_3 VALUES LESS THAN (2),
PARTITION item_4 VALUES LESS THAN (3),
PARTITION item_5 VALUES LESS THAN (6),
PARTITION item_6 VALUES LESS THAN (8),
PARTITION item_7 VALUES LESS THAN (10),
PARTITION item_8 VALUES LESS THAN (15),
PARTITION item_9 VALUES LESS THAN (MAXVALUE)
) ENABLE ROW MOVEMENT;
NOTICE: CREATE TABLE / UNIQUE will create implicit index "u_item_index" for table "item"
CREATE TABLE region
(
a INT DEFAULT 8,
region_cd VARCHAR(50),
region_name VARCHAR(100),
division_cd VARCHAR(50),
region_mgr_associate_id number(18,9)
);
CREATE TABLE associate_benefit_expense
(
a INT DEFAULT 44,
period_end_dt DATE,
associate_expns_type_cd VARCHAR(50),
associate_party_id INTEGER,
benefit_hours_qty decimal(38,11),
benefit_cost_amt number(38,4)
)
PARTITION BY RANGE (associate_expns_type_cd)
(
PARTITION associate_benefit_expense_1 VALUES LESS THAN ('B'),
PARTITION associate_benefit_expense_2 VALUES LESS THAN ('E'),
PARTITION associate_benefit_expense_3 VALUES LESS THAN ('G'),
PARTITION associate_benefit_expense_4 VALUES LESS THAN ('I'),
PARTITION associate_benefit_expense_5 VALUES LESS THAN ('L'),
PARTITION associate_benefit_expense_6 VALUES LESS THAN ('N'),
PARTITION associate_benefit_expense_7 VALUES LESS THAN ('P'),
PARTITION associate_benefit_expense_8 VALUES LESS THAN ('Q'),
PARTITION associate_benefit_expense_9 VALUES LESS THAN ('R'),
PARTITION associate_benefit_expense_10 VALUES LESS THAN ('T'),
PARTITION associate_benefit_expense_11 VALUES LESS THAN ('U'),
PARTITION associate_benefit_expense_12 VALUES LESS THAN ('V'),
PARTITION associate_benefit_expense_13 VALUES LESS THAN (MAXVALUE)
) ENABLE ROW MOVEMENT;
INSERT INTO item (ITEM_ID, ITEM_NAME, ITEM_DESC, ITEM_SUBCLASS_CD, ITEM_TYPE_CD, INVENTORY_IND, VENDOR_PARTY_ID, COMMODITY_CD, BRAND_CD,ITEM_AVAILABLE) VALUES (0.12, ' ' , 'A' , NULL, 'TGK' , 'A' , 2, 'A' , 'A' , 'Y');
INSERT INTO item (ITEM_ID, ITEM_NAME, ITEM_DESC, ITEM_SUBCLASS_CD, ITEM_TYPE_CD, INVENTORY_IND, VENDOR_PARTY_ID, COMMODITY_CD, BRAND_CD,ITEM_AVAILABLE) VALUES (1.3, 'B' , NULL, 'B' , 'B' , NULL, 1, 'B' , NULL , 'N');
INSERT INTO item (ITEM_ID, ITEM_NAME, ITEM_DESC, ITEM_SUBCLASS_CD, ITEM_TYPE_CD, INVENTORY_IND, VENDOR_PARTY_ID, COMMODITY_CD, BRAND_CD,ITEM_AVAILABLE) VALUES (2.23, 'C' , 'C' , NULL, 'C' , 'C' , 2, 'C' , 'C' , 'N');
INSERT INTO item (ITEM_ID, ITEM_NAME, ITEM_DESC, ITEM_SUBCLASS_CD, ITEM_TYPE_CD, INVENTORY_IND, VENDOR_PARTY_ID, COMMODITY_CD, BRAND_CD,ITEM_AVAILABLE) VALUES (3.33, 'D' , 'D' , 'PT' , NULL, 'D' , 3, 'D' , 'D' , 'N');
INSERT INTO item (ITEM_ID, ITEM_NAME, ITEM_DESC, ITEM_SUBCLASS_CD, ITEM_TYPE_CD, INVENTORY_IND, VENDOR_PARTY_ID, COMMODITY_CD, BRAND_CD,ITEM_AVAILABLE) VALUES (4.98, ' ' , NULL, 'E' , 'E' , 'E' , 4, 'E' , 'E' , 'Y');
INSERT INTO item (ITEM_ID, ITEM_NAME, ITEM_DESC, ITEM_SUBCLASS_CD, ITEM_TYPE_CD, INVENTORY_IND, VENDOR_PARTY_ID, COMMODITY_CD, BRAND_CD,ITEM_AVAILABLE) VALUES (5.01, NULL, 'F' , ' ' , 'F' , 'F' , 5, 'F' , 'F' , 'N');
INSERT INTO item (ITEM_ID, ITEM_NAME, ITEM_DESC, ITEM_SUBCLASS_CD, ITEM_TYPE_CD, INVENTORY_IND, VENDOR_PARTY_ID, COMMODITY_CD, BRAND_CD,ITEM_AVAILABLE) VALUES (6, 'G' , 'G' , 'G' , '_D' , 'G' , 6, 'G' , NULL ,'N');
INSERT INTO item (ITEM_ID, ITEM_NAME, ITEM_DESC, ITEM_SUBCLASS_CD, ITEM_TYPE_CD, INVENTORY_IND, VENDOR_PARTY_ID, COMMODITY_CD, BRAND_CD,ITEM_AVAILABLE) VALUES (0.7, NULL, NULL, NULL, 'H' , 'H' , 7, NULL, 'G' , 'Y');
INSERT INTO item (ITEM_ID, ITEM_NAME, ITEM_DESC, ITEM_SUBCLASS_CD, ITEM_TYPE_CD, INVENTORY_IND, VENDOR_PARTY_ID, COMMODITY_CD, BRAND_CD,ITEM_AVAILABLE) VALUES (0.08, 'I' , ' ' , ' T ' , NULL, 'I' , 8, 'I' , '' , 'N');
INSERT INTO item (ITEM_ID, ITEM_NAME, ITEM_DESC, ITEM_SUBCLASS_CD, ITEM_TYPE_CD, INVENTORY_IND, VENDOR_PARTY_ID, COMMODITY_CD, BRAND_CD,ITEM_AVAILABLE) VALUES (9.12, ' ' , 'J' , ' PP' , 'J' , 'J' , 9, 'J' , NULL , 'Y');
INSERT INTO item (ITEM_ID, ITEM_NAME, ITEM_DESC, ITEM_SUBCLASS_CD, ITEM_TYPE_CD, INVENTORY_IND, VENDOR_PARTY_ID, COMMODITY_CD, BRAND_CD,ITEM_AVAILABLE) VALUES (10.10, NULL, ' ' , 'A' , 'A' , 'A' , 2, NULL, 'A','Y');
--INSERT INTO item (ITEM_ID, ITEM_NAME, ITEM_DESC, ITEM_SUBCLASS_CD, ITEM_TYPE_CD, INVENTORY_IND, VENDOR_PARTY_ID, COMMODITY_CD, BRAND_CD,ITEM_AVAILABLE) VALUES (11.11, 'B' , 'B' , 'B' , 'BCDAA' , NULL, 1, 'B' , 'B','N');
INSERT INTO item (ITEM_ID, ITEM_NAME, ITEM_DESC, ITEM_SUBCLASS_CD, ITEM_TYPE_CD, INVENTORY_IND, VENDOR_PARTY_ID, COMMODITY_CD, BRAND_CD,ITEM_AVAILABLE) VALUES (12.02, 'D' , NULL, NULL, 'C' , 'C' , 2, 'C' , 'C','N');
INSERT INTO item (ITEM_ID, ITEM_NAME, ITEM_DESC, ITEM_SUBCLASS_CD, ITEM_TYPE_CD, INVENTORY_IND, VENDOR_PARTY_ID, COMMODITY_CD, BRAND_CD,ITEM_AVAILABLE) VALUES (13.99, NULL, ' ' , 'D' , 'D' , 'D' , 3, 'D' , 'D','Y');
--INSERT INTO item (ITEM_ID, ITEM_NAME, ITEM_DESC, ITEM_SUBCLASS_CD, ITEM_TYPE_CD, INVENTORY_IND, VENDOR_PARTY_ID, COMMODITY_CD, BRAND_CD,ITEM_AVAILABLE) VALUES (14, 'G' , 'E' , 'E' , NULL, 'E' , 4, 'E' , 'E','N');
INSERT INTO item (ITEM_ID, ITEM_NAME, ITEM_DESC, ITEM_SUBCLASS_CD, ITEM_TYPE_CD, INVENTORY_IND, VENDOR_PARTY_ID, COMMODITY_CD, BRAND_CD,ITEM_AVAILABLE) VALUES (15, 'F' , ' ' , 'C' , 'CLEANING' , 'F' , 5, 'F' , 'F','Y');
INSERT INTO item (ITEM_ID, ITEM_NAME, ITEM_DESC, ITEM_SUBCLASS_CD, ITEM_TYPE_CD, INVENTORY_IND, VENDOR_PARTY_ID, COMMODITY_CD, BRAND_CD,ITEM_AVAILABLE) VALUES (16, '' , 'Z' , NULL, 'G' , 'G' , 6, 'G' , NULL,'N');
INSERT INTO item (ITEM_ID, ITEM_NAME, ITEM_DESC, ITEM_SUBCLASS_CD, ITEM_TYPE_CD, INVENTORY_IND, VENDOR_PARTY_ID, COMMODITY_CD, BRAND_CD,ITEM_AVAILABLE) VALUES (17, NULL, '' , ' PAPER' , 'H' , '' , 7, NULL, NULL,'Y');
INSERT INTO item (ITEM_ID, ITEM_NAME, ITEM_DESC, ITEM_SUBCLASS_CD, ITEM_TYPE_CD, INVENTORY_IND, VENDOR_PARTY_ID, COMMODITY_CD, BRAND_CD,ITEM_AVAILABLE) VALUES (19, ' ' , 'B' , '' , '' , 'I' , 8, 'I' , NULL,'N');
INSERT INTO item (ITEM_ID, ITEM_NAME, ITEM_DESC, ITEM_SUBCLASS_CD, ITEM_TYPE_CD, INVENTORY_IND, VENDOR_PARTY_ID, COMMODITY_CD, BRAND_CD,ITEM_AVAILABLE) VALUES (20 , 'A' , 'J' , 'J' , 'J' , NULL, 9, 'J' , 'G','Y');
/*--REGION--*/
INSERT INTO REGION (REGION_CD, REGION_NAME, DIVISION_CD, REGION_MGR_ASSOCIATE_ID) VALUES ('A', 'A ', 'A', 0.123433);
INSERT INTO REGION (REGION_CD, REGION_NAME, DIVISION_CD, REGION_MGR_ASSOCIATE_ID) VALUES ('B', 'B', 'B', NULL);
INSERT INTO REGION (REGION_CD, REGION_NAME, DIVISION_CD, REGION_MGR_ASSOCIATE_ID) VALUES ('C', 'C', 'C', 2.232008908);
INSERT INTO REGION (REGION_CD, REGION_NAME, DIVISION_CD, REGION_MGR_ASSOCIATE_ID) VALUES ('D', ' DD', 'D', 3.878789);
INSERT INTO REGION (REGION_CD, REGION_NAME, DIVISION_CD, REGION_MGR_ASSOCIATE_ID) VALUES ('E', 'A', 'E', 4.89060603);
INSERT INTO REGION (REGION_CD, REGION_NAME, DIVISION_CD, REGION_MGR_ASSOCIATE_ID) VALUES ('F', 'F', 'F', 5.82703827);
INSERT INTO REGION (REGION_CD, REGION_NAME, DIVISION_CD, REGION_MGR_ASSOCIATE_ID) VALUES ('G', 'G', 'TTT', NULL);
INSERT INTO REGION (REGION_CD, REGION_NAME, DIVISION_CD, REGION_MGR_ASSOCIATE_ID) VALUES ('H', 'H', 'G', 7.3829083);
INSERT INTO REGION (REGION_CD, REGION_NAME, DIVISION_CD, REGION_MGR_ASSOCIATE_ID) VALUES ('I', 'C', 'M', 8.983989);
INSERT INTO REGION (REGION_CD, REGION_NAME, DIVISION_CD, REGION_MGR_ASSOCIATE_ID) VALUES ('J', 'J', 'G', NULL);
INSERT INTO REGION (REGION_CD, REGION_NAME, DIVISION_CD, REGION_MGR_ASSOCIATE_ID) VALUES ('K', ' ', 'C', 2.232008908);
INSERT INTO REGION (REGION_CD, REGION_NAME, DIVISION_CD, REGION_MGR_ASSOCIATE_ID) VALUES ('L', 'D', 'X', 3.878789);
INSERT INTO REGION (REGION_CD, REGION_NAME, DIVISION_CD, REGION_MGR_ASSOCIATE_ID) VALUES ('M', 'TTTTTT ', 'D' , 4.89060603);
INSERT INTO REGION (REGION_CD, REGION_NAME, DIVISION_CD, REGION_MGR_ASSOCIATE_ID) VALUES ('N', 'G' , 'B' , NULL);
INSERT INTO REGION (REGION_CD, REGION_NAME, DIVISION_CD, REGION_MGR_ASSOCIATE_ID) VALUES ('O' , 'G', 'F', 6.6703972);
INSERT INTO ASSOCIATE_BENEFIT_EXPENSE (PERIOD_END_DT, ASSOCIATE_EXPNS_TYPE_CD, ASSOCIATE_PARTY_ID, BENEFIT_HOURS_QTY, BENEFIT_COST_AMT) VALUES (DATE '1970-01-01', 'A', 5, 0.5 , 0.5);
INSERT INTO ASSOCIATE_BENEFIT_EXPENSE (PERIOD_END_DT, ASSOCIATE_EXPNS_TYPE_CD, ASSOCIATE_PARTY_ID, BENEFIT_HOURS_QTY, BENEFIT_COST_AMT) VALUES (DATE '1973-01-01', 'B', 1, NULL, 1.0);
INSERT INTO ASSOCIATE_BENEFIT_EXPENSE (PERIOD_END_DT, ASSOCIATE_EXPNS_TYPE_CD, ASSOCIATE_PARTY_ID, BENEFIT_HOURS_QTY, BENEFIT_COST_AMT) VALUES (DATE '1976-01-01', 'C', 2, 2.0 , NULL);
INSERT INTO ASSOCIATE_BENEFIT_EXPENSE (PERIOD_END_DT, ASSOCIATE_EXPNS_TYPE_CD, ASSOCIATE_PARTY_ID, BENEFIT_HOURS_QTY, BENEFIT_COST_AMT) VALUES (DATE '1979-01-01', 'D', 3, 3.0 , 3.0);
INSERT INTO ASSOCIATE_BENEFIT_EXPENSE (PERIOD_END_DT, ASSOCIATE_EXPNS_TYPE_CD, ASSOCIATE_PARTY_ID, BENEFIT_HOURS_QTY, BENEFIT_COST_AMT) VALUES (DATE '1982-01-01', 'E', 4, 4.0 , 4.0);
INSERT INTO ASSOCIATE_BENEFIT_EXPENSE (PERIOD_END_DT, ASSOCIATE_EXPNS_TYPE_CD, ASSOCIATE_PARTY_ID, BENEFIT_HOURS_QTY, BENEFIT_COST_AMT) VALUES (DATE '1985-01-01', 'F', 5, 5.0 , 5.0);
INSERT INTO ASSOCIATE_BENEFIT_EXPENSE (PERIOD_END_DT, ASSOCIATE_EXPNS_TYPE_CD, ASSOCIATE_PARTY_ID, BENEFIT_HOURS_QTY, BENEFIT_COST_AMT) VALUES (DATE '1988-01-01', 'F', 6, NULL, 6.0);
INSERT INTO ASSOCIATE_BENEFIT_EXPENSE (PERIOD_END_DT, ASSOCIATE_EXPNS_TYPE_CD, ASSOCIATE_PARTY_ID, BENEFIT_HOURS_QTY, BENEFIT_COST_AMT) VALUES (DATE '1991-01-01', 'G', 6, NULL, NULL);
INSERT INTO ASSOCIATE_BENEFIT_EXPENSE (PERIOD_END_DT, ASSOCIATE_EXPNS_TYPE_CD, ASSOCIATE_PARTY_ID, BENEFIT_HOURS_QTY, BENEFIT_COST_AMT) VALUES (DATE '1994-01-01', 'G', 15, 8.0 , 8.0);
INSERT INTO ASSOCIATE_BENEFIT_EXPENSE (PERIOD_END_DT, ASSOCIATE_EXPNS_TYPE_CD, ASSOCIATE_PARTY_ID, BENEFIT_HOURS_QTY, BENEFIT_COST_AMT) VALUES (DATE '1997-01-01', 'G', 16, 9.0 , 9.0);
INSERT INTO ASSOCIATE_BENEFIT_EXPENSE (PERIOD_END_DT, ASSOCIATE_EXPNS_TYPE_CD, ASSOCIATE_PARTY_ID, BENEFIT_HOURS_QTY, BENEFIT_COST_AMT) VALUES (DATE '1983-01-03', 'I', 14, 4.0 , 4.0);
INSERT INTO ASSOCIATE_BENEFIT_EXPENSE (PERIOD_END_DT, ASSOCIATE_EXPNS_TYPE_CD, ASSOCIATE_PARTY_ID, BENEFIT_HOURS_QTY, BENEFIT_COST_AMT) VALUES (DATE '1984-01-01', 'GO', 15, 5.0 , NULL);
INSERT INTO ASSOCIATE_BENEFIT_EXPENSE (PERIOD_END_DT, ASSOCIATE_EXPNS_TYPE_CD, ASSOCIATE_PARTY_ID, BENEFIT_HOURS_QTY, BENEFIT_COST_AMT) VALUES (DATE '1985-05-01', 'I', 16, 6.0 , 6.0);
INSERT INTO ASSOCIATE_BENEFIT_EXPENSE (PERIOD_END_DT, ASSOCIATE_EXPNS_TYPE_CD, ASSOCIATE_PARTY_ID, BENEFIT_HOURS_QTY, BENEFIT_COST_AMT) VALUES (DATE '1990-01-01', 'TTT', 16, NULL, 7.0);
INSERT INTO ASSOCIATE_BENEFIT_EXPENSE (PERIOD_END_DT, ASSOCIATE_EXPNS_TYPE_CD, ASSOCIATE_PARTY_ID, BENEFIT_HOURS_QTY, BENEFIT_COST_AMT) VALUES (DATE '1992-02-01', 'A', 15, 8.0 , 8.0);
INSERT INTO ASSOCIATE_BENEFIT_EXPENSE (PERIOD_END_DT, ASSOCIATE_EXPNS_TYPE_CD, ASSOCIATE_PARTY_ID, BENEFIT_HOURS_QTY, BENEFIT_COST_AMT) VALUES (DATE '1997-02-01', 'G', 17, 9.0 , NULL);
INSERT INTO ASSOCIATE_BENEFIT_EXPENSE (PERIOD_END_DT, ASSOCIATE_EXPNS_TYPE_CD, ASSOCIATE_PARTY_ID, BENEFIT_HOURS_QTY, BENEFIT_COST_AMT) VALUES (DATE '1997-05-01', 'G' , 17, 9.0 , NULL);
ANALYZE item;
ANALYZE region;
ANALYZE associate_benefit_expense;
EXPLAIN (VERBOSE ON, COSTS OFF)
INSERT INTO item (item_level, item_subclass_cd, item_desc, vendor_party_id)
SELECT Table_001.REGION_MGR_ASSOCIATE_ID Column_003,
Table_002.associate_expns_type_cd Column_004,
CAST(Table_001.region_name AS VARCHAR) Column_005,
10 Column_006
-- 'o' Column_007,
-- 'F' Column_008,
-- pg_client_encoding() Column_009
FROM region Table_001, associate_benefit_expense Table_002
ON DUPLICATE KEY UPDATE item_level = -1000;
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Insert on test_insert_update_008.item
Conflict Resolution: UPDATE
Conflict Arbiter Indexes: u_item_index
-> Nested Loop
Output: 3, NULL::numeric, NULL::character varying, table_001.region_mgr_associate_id, (table_001.region_name)::character varying(250), table_002.associate_expns_type_cd, NULL::character varying, NULL::bpchar, 10::smallint, NULL::character varying, NULL::character varying, NULL::bpchar
-> Partition Iterator
Output: table_002.a, table_002.period_end_dt, table_002.associate_expns_type_cd, table_002.associate_party_id, table_002.benefit_hours_qty, table_002.benefit_cost_amt
Iterations: 13
-> Partitioned Seq Scan on test_insert_update_008.associate_benefit_expense table_002
Output: table_002.a, table_002.period_end_dt, table_002.associate_expns_type_cd, table_002.associate_party_id, table_002.benefit_hours_qty, table_002.benefit_cost_amt
Selected Partitions: 1..13
-> Materialize
Output: table_001.region_mgr_associate_id, table_001.region_name
-> Seq Scan on test_insert_update_008.region table_001
Output: table_001.region_mgr_associate_id, table_001.region_name
(15 rows)
EXPLAIN (VERBOSE ON, COSTS OFF)
INSERT INTO products_row VALUES(100)
ON DUPLICATE KEY UPDATE total=100;
QUERY PLAN
-----------------------------------------------------------------------------------------
Insert on test_insert_update_008.products_row
Conflict Resolution: UPDATE
Conflict Arbiter Indexes: products_row_pkey
-> Result
Output: 100, 'null'::character varying(60), 'unknown'::character varying(60), 0
(5 rows)
SET enable_light_proxy=off;
EXPLAIN (VERBOSE ON, COSTS OFF)
INSERT INTO products_row VALUES(100)
ON DUPLICATE KEY UPDATE total=100;
QUERY PLAN
-----------------------------------------------------------------------------------------
Insert on test_insert_update_008.products_row
Conflict Resolution: UPDATE
Conflict Arbiter Indexes: products_row_pkey
-> Result
Output: 100, 'null'::character varying(60), 'unknown'::character varying(60), 0
(5 rows)
EXPLAIN (VERBOSE ON, COSTS OFF)
INSERT INTO products_row VALUES(100)
ON DUPLICATE KEY UPDATE total=100;
QUERY PLAN
-----------------------------------------------------------------------------------------
Insert on test_insert_update_008.products_row
Conflict Resolution: UPDATE
Conflict Arbiter Indexes: products_row_pkey
-> Result
Output: 100, 'null'::character varying(60), 'unknown'::character varying(60), 0
(5 rows)
EXPLAIN (VERBOSE ON, COSTS OFF)
INSERT INTO products_row VALUES(100)
ON DUPLICATE KEY UPDATE total=100;
QUERY PLAN
-----------------------------------------------------------------------------------------
Insert on test_insert_update_008.products_row
Conflict Resolution: UPDATE
Conflict Arbiter Indexes: products_row_pkey
-> Result
Output: 100, 'null'::character varying(60), 'unknown'::character varying(60), 0
(5 rows)
RESET enable_light_proxy;
DROP SCHEMA test_insert_update_008 CASCADE;
NOTICE: drop cascades to 7 other objects
DETAIL: drop cascades to table products_base
drop cascades to table newproducts_base
drop cascades to table products_row
drop cascades to table newproducts_row
drop cascades to table item
drop cascades to table region
drop cascades to table associate_benefit_expense

View File

@ -0,0 +1,548 @@
DROP SCHEMA test_insert_update_009 CASCADE;
ERROR: schema "test_insert_update_009" does not exist
CREATE SCHEMA test_insert_update_009;
SET CURRENT_SCHEMA TO test_insert_update_009;
SET enable_light_proxy=off;
-- enable_upsert_to_merge must is off, or upsert will be translated to merge.
SET enable_upsert_to_merge TO OFF;
-- test t1 with no index
CREATE TABLE t1 (
col1 INT,
col2 INT,
col3 INT DEFAULT 1,
-- col4 TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
col5 BIGSERIAL
) ;
NOTICE: CREATE TABLE will create implicit sequence "t1_col5_seq" for serial column "t1.col5"
--- distribute key are not allowed to update
INSERT INTO t1 VALUES (1, 2) ON DUPLICATE KEY UPDATE col1 = 3;
--- should always insert
INSERT INTO t1 VALUES (1, 2) ON DUPLICATE KEY UPDATE col2 = 3;
INSERT INTO t1 VALUES (1, 2) ON DUPLICATE KEY UPDATE t1.col2 = 4;
--- appoint column list in insert clause, should always insert
INSERT INTO t1(col1, col3) VALUES (1, 3) ON DUPLICATE KEY UPDATE col2 = 5;
INSERT INTO t1(col1, col3) VALUES (1, 3) ON DUPLICATE KEY UPDATE t1.col2 = 6;
--- multiple rows, should always insert
INSERT INTO t1 VALUES (2, 1), (2, 1) ON DUPLICATE KEY UPDATE col2 = 7, col3 = 7;
SELECT * FROM t1 ORDER BY col5;
col1 | col2 | col3 | col5
------+------+------+------
1 | 2 | 1 | 1
1 | 2 | 1 | 2
1 | 2 | 1 | 3
1 | | 3 | 4
1 | | 3 | 5
2 | 1 | 1 | 6
2 | 1 | 1 | 7
(7 rows)
--- test union, should insert
INSERT INTO t1 (col1, col2)
SELECT * FROM
(SELECT col1, col2 FROM t1
UNION
SELECT col1, col3 FROM t1) AS union_table
ON DUPLICATE KEY UPDATE col3 = (col1 + col2 + col3);
SELECT col1, col2, col3 FROM t1 WHERE col5 > 6 ORDER BY col1, col2;
col1 | col2 | col3
------+------+------
1 | 1 | 1
1 | 2 | 1
1 | 3 | 1
1 | | 1
2 | 1 | 1
2 | 1 | 1
(6 rows)
--- test subquery, should insert
INSERT INTO t1
(SELECT col1 || col2 || '00' FROM t1 ORDER BY col5)
ON DUPLICATE KEY UPDATE col3 = col1 * 100;
SELECT col1, col2, col3 FROM t1 WHERE col1 >= 100 ORDER BY col1;
col1 | col2 | col3
------+------+------
100 | | 1
100 | | 1
100 | | 1
1100 | | 1
1200 | | 1
1200 | | 1
1200 | | 1
1200 | | 1
1300 | | 1
2100 | | 1
2100 | | 1
2100 | | 1
(12 rows)
-- test t2 with one primary key
CREATE TABLE t2 (
col1 INT,
col2 INT PRIMARY KEY,
col3 INT DEFAULT 1,
col4 TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
col5 BIGSERIAL
) ;
NOTICE: CREATE TABLE will create implicit sequence "t2_col5_seq" for serial column "t2.col5"
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "t2_pkey" for table "t2"
--- distribute key are not allowed to update
INSERT INTO t2 VALUES (1, 1) ON DUPLICATE KEY UPDATE col2 = 3;
ERROR: INSERT ON DUPLICATE KEY UPDATE don't allow update on primary key or unique key.
INSERT INTO t2 VALUES (1, 1) ON DUPLICATE KEY UPDATE t2.col2 = 3;
ERROR: INSERT ON DUPLICATE KEY UPDATE don't allow update on primary key or unique key.
INSERT INTO t2 (col2, col3, col4, col5)
VALUES (10, 10, CURRENT_TIMESTAMP(0), 10),
(20, 20, CURRENT_TIMESTAMP(1), 20),
(30, 30, CURRENT_TIMESTAMP(2), 30)
ON DUPLICATE KEY UPDATE
col1 = 100,
col2 = 100,
col3 = 100,
col4 = '2019-08-09'::TIMESTAMP,
col5 = 100;
ERROR: INSERT ON DUPLICATE KEY UPDATE don't allow update on primary key or unique key.
--- should insert
INSERT INTO t2 VALUES (1, 1) ON DUPLICATE KEY UPDATE col1 = 30;
INSERT INTO t2 VALUES (2, 2) ON DUPLICATE KEY UPDATE t2.col1 = 40;
INSERT INTO t2 VALUES (3, 3) ON DUPLICATE KEY UPDATE col1 = col1 * 2;
INSERT INTO t2 VALUES (4, 4) ON DUPLICATE KEY UPDATE t2.col1 = t2.col1 * 2 ;
INSERT INTO t2 VALUES (5, 5) ON DUPLICATE KEY UPDATE col1 = col2 + 1;
INSERT INTO t2 VALUES (6, 6) ON DUPLICATE KEY UPDATE t2.col1 = t2.col2 + 1;
INSERT INTO t2 VALUES (7, 7) ON DUPLICATE KEY UPDATE col1 = extract(dow from col4) + 10;
INSERT INTO t2 VALUES (8, 8) ON DUPLICATE KEY UPDATE t2.col1 = extract(century from col4) * 100 + extract(isodow from col4);
SELECT col1, col2, col3, col5 FROM t2 ORDER BY col5;
col1 | col2 | col3 | col5
------+------+------+------
1 | 1 | 1 | 1
2 | 2 | 1 | 2
3 | 3 | 1 | 3
4 | 4 | 1 | 4
5 | 5 | 1 | 5
6 | 6 | 1 | 6
7 | 7 | 1 | 7
8 | 8 | 1 | 8
(8 rows)
--- should update
INSERT INTO t2 VALUES (3, 1) ON DUPLICATE KEY UPDATE col1 = 30, col3 = col5 + 1;
INSERT INTO t2 VALUES (4, 2) ON DUPLICATE KEY UPDATE t2.col1 = 40, t2.col3 = t2.col5;
INSERT INTO t2 VALUES (3, 3), (4, 4) ON DUPLICATE KEY UPDATE col3 = t2.col5 + 1;
INSERT INTO t2 VALUES (5, 5) ON DUPLICATE KEY UPDATE col1 = extract(dow from col4) + 10;
INSERT INTO t2 VALUES (6, 6) ON DUPLICATE KEY UPDATE t2.col1 = extract(century from col4) * 100 + extract(isodow from col4);
SELECT col1, col2, col3, col5 FROM t2 ORDER BY col5;
col1 | col2 | col3 | col5
------+------+------+------
30 | 1 | 2 | 1
40 | 2 | 2 | 2
3 | 3 | 4 | 3
4 | 4 | 5 | 4
--?.*| 5 | 1 | 5
--?.*| 6 | 1 | 6
7 | 7 | 1 | 7
8 | 8 | 1 | 8
(8 rows)
-- primary key are not allowed to be null
INSERT INTO t2 (col1) VALUES (10) ON DUPLICATE KEY UPDATE col1 = 10;
ERROR: null value in column "col2" violates not-null constraint
--?
--- appoint column list in insert clause
---- should insert
INSERT INTO t2 (col2, col3) VALUES (9, 9) ON DUPLICATE KEY UPDATE col1 = 90;
INSERT INTO t2 (col2, col3, col4, col5)
VALUES (10, 10, CURRENT_TIMESTAMP(0), 10),
(20, 20, CURRENT_TIMESTAMP(1), 20),
(30, 30, CURRENT_TIMESTAMP(2), 30)
ON DUPLICATE KEY UPDATE
col1 = 100,
col3 = 100,
col4 = '2019-08-20'::TIMESTAMP,
col5 = 100;
SELECT * FROM t2 ORDER BY col5;
col1 | col2 | col3 | col4 | col5
------+------+------+---------------------------------+------
--? 30 | 1 | 2 | .* | 1
--? 40 | 2 | 2 | .* | 2
--? 3 | 3 | 4 | .* | 3
--? 4 | 4 | 5 | .* | 4
--? .* | 5 | 1 | .* | 5
--? .* | 6 | 1 | .* | 6
--? 7 | 7 | 1 | .* | 7
--? 8 | 8 | 1 | .* | 8
--? | 9 | 9 | .* | 10
--? | 10 | 10 | .* | 10
--? | 20 | 20 | .* | 20
--? | 30 | 30 | .* | 30
(12 rows)
---- should update
INSERT INTO t2 (col2, col3) VALUES (9, 9) ON DUPLICATE KEY UPDATE col1 = 90;
INSERT INTO t2 (col2, col3, col4, col5)
VALUES (10, 10, CURRENT_TIMESTAMP(0), 10),
(20, 20, CURRENT_TIMESTAMP(1), 20),
(30, 30, CURRENT_TIMESTAMP(2), 30)
ON DUPLICATE KEY UPDATE
col1 = 100,
col3 = 100,
col4 = '2019-08-20'::TIMESTAMP,
col5 = 100;
SELECT * FROM t2 ORDER BY col5, col2;
col1 | col2 | col3 | col4 | col5
------+------+------+---------------------------------+------
--? 30 | 1 | 2 | .* | 1
--? 40 | 2 | 2 | .* | 2
--? 3 | 3 | 4 | .* | 3
--? 4 | 4 | 5 | .* | 4
--? .* | 5 | 1 | .* | 5
--? .* | 6 | 1 | .* | 6
--? 7 | 7 | 1 | .* | 7
--? 8 | 8 | 1 | .* | 8
--? 90 | 9 | 9 | .* | 10
100 | 10 | 100 | Tue Aug 20 00:00:00 2019 | 100
100 | 20 | 100 | Tue Aug 20 00:00:00 2019 | 100
100 | 30 | 100 | Tue Aug 20 00:00:00 2019 | 100
(12 rows)
--- test subquery
---- should insert
INSERT INTO t2
(SELECT col1 * 1000, col2 * 1000 + 1 FROM t2 ORDER BY col5 LIMIT 2)
ON DUPLICATE KEY UPDATE col3 = col2 + 1;
INSERT INTO t2 (col2, col3)
(SELECT col1 * 1000 + 2, col2 * 1000 FROM t2 ORDER BY col5 LIMIT 2 OFFSET 1)
ON DUPLICATE KEY UPDATE col3 = col2 + 1;
SELECT col1, col2, col3, col5 FROM t2 ORDER BY col5, col2;
col1 | col2 | col3 | col5
-------+-------+------+------
30 | 1 | 2 | 1
40 | 2 | 2 | 2
3 | 3 | 4 | 3
4 | 4 | 5 | 4
--? .* | 5 | 1 | 5
--? .* | 6 | 1 | 6
7 | 7 | 1 | 7
8 | 8 | 1 | 8
90 | 9 | 9 | 16
--? 30000 | 1001 | 1 | 11
--? 40000 | 2001 | 1 | 12
--? | 40002 | 2000 | 13
--? | 3002 | 3000 | 14
100 | 10 | 100 | 100
100 | 20 | 100 | 100
100 | 30 | 100 | 100
(16 rows)
---- should update
INSERT INTO t2
(SELECT col1 * 1000, col2 * 1000 + 1 FROM t2 ORDER BY col5 LIMIT 2)
ON DUPLICATE KEY UPDATE col3 = col2 + 1;
INSERT INTO t2 (col2, col3)
(SELECT col1 * 1000 + 2, col2 * 1000 FROM t2 ORDER BY col5 LIMIT 2 OFFSET 1)
ON DUPLICATE KEY UPDATE col3 = col2 + 1;
SELECT col1, col2, col3, col5 FROM t2 ORDER BY col5, col2;
col1 | col2 | col3 | col5
-------+-------+-------+------
30 | 1 | 2 | 1
40 | 2 | 2 | 2
3 | 3 | 4 | 3
4 | 4 | 5 | 4
--? 2 | 5 | 1 | 5
--? 2101 | 6 | 1 | 6
7 | 7 | 1 | 7
8 | 8 | 1 | 8
90 | 9 | 9 | 16
--? 30000 | 1001 | 1002 | 11
--? 40000 | 2001 | 2002 | 12
--? | 40002 | 40003 | 13
--? | 3002 | 3003 | 14
100 | 10 | 100 | 100
100 | 20 | 100 | 100
100 | 30 | 100 | 100
(16 rows)
--- test union, some insert some update
SELECT col1, col2 FROM t1 WHERE col2 IS NOT NULL
UNION
SELECT col1, col3 FROM t1 ORDER BY 1, 2;
col1 | col2
------+------
1 | 1
1 | 2
1 | 3
2 | 1
100 | 1
1100 | 1
1200 | 1
1300 | 1
2100 | 1
(9 rows)
INSERT INTO t2 (col1, col2)
SELECT * FROM
(SELECT col1, col2 FROM t1 WHERE col2 IS NOT NULL
UNION
SELECT col1, col3 FROM t1) AS union_table
ON DUPLICATE KEY UPDATE col3 = (col1 + col2 + col3);
SELECT col1, col2, col3, col5 FROM t2 ORDER BY col5, col2;
col1 | col2 | col3 | col5
-------+-------+-------+------
30 | 1 | 219 | 1
40 | 2 | 44 | 2
3 | 3 | 10 | 3
4 | 4 | 5 | 4
--? .* | 5 | 1 | 5
--? .* | 6 | 1 | 6
7 | 7 | 1 | 7
8 | 8 | 1 | 8
90 | 9 | 9 | 16
--? 30000 | 1001 | 1002 | 11
--? 40000 | 2001 | 2002 | 12
--? | 40002 | 40003 | 13
--? | 3002 | 3003 | 14
100 | 10 | 100 | 100
100 | 20 | 100 | 100
100 | 30 | 100 | 100
(16 rows)
INSERT INTO t2 (col1, col2)
SELECT col1, col2 FROM t1 WHERE col2 IS NOT NULL
UNION
SELECT col1, col3 FROM t1
ON DUPLICATE KEY UPDATE col3 = (col1 + col2 + col3);
SELECT col1, col2, col3, col5 FROM t2 ORDER BY col5, col2;
col1 | col2 | col3 | col5
-------+-------+-------+------
30 | 1 | 436 | 1
40 | 2 | 86 | 2
3 | 3 | 16 | 3
4 | 4 | 5 | 4
--? 15 | 5 | 1 | 5
--? 2105 | 6 | 1 | 6
7 | 7 | 1 | 7
8 | 8 | 1 | 8
90 | 9 | 9 | 16
--? 30000 | 1001 | 1002 | 11
--? 40000 | 2001 | 2002 | 12
--? | 40002 | 40003 | 13
--? | 3002 | 3003 | 14
100 | 10 | 100 | 100
100 | 20 | 100 | 100
100 | 30 | 100 | 100
(16 rows)
reset behavior_compat_options;
-- test INTERSECT, should update
(SELECT col1, col1 + col2 FROM t1 WHERE col2 IS NOT NULL
UNION
SELECT 1, 2)
INTERSECT
SELECT col1, col3 FROM t1;
col1 | ?column?
------+----------
1 | 3
(1 row)
INSERT INTO t2 (col1, col2)
(SELECT col1, col1 + col2 FROM t1 WHERE col2 IS NOT NULL
UNION
SELECT 1, 2)
INTERSECT
SELECT col1, col3 FROM t1
ON DUPLICATE KEY UPDATE col3 = (col1 + col2 + col3);
SELECT col1, col2, col3, col5 FROM t2 WHERE col2 = 3 ORDER BY col5, col2;
col1 | col2 | col3 | col5
------+------+------+------
3 | 3 | 22 | 3
(1 row)
-- test EXCEPT, should update
SELECT col1, col2 FROM t1 WHERE col2 IS NOT NULL
EXCEPT
(SELECT col1, col3 FROM t1
UNION
SELECT NULL, NULL);
col1 | col2
------+------
1 | 2
(1 row)
INSERT INTO t2 (col1, col2)
SELECT col1, col2 FROM t1 WHERE col2 IS NOT NULL
EXCEPT
(SELECT col1, col3 FROM t1
UNION
SELECT NULL, NULL)
ON DUPLICATE KEY UPDATE col3 = (col1 + col2 + col3);
SELECT col1, col2, col3, col5 FROM t2 WHERE col2 = 2 ORDER BY col5, col2;
col1 | col2 | col3 | col5
------+------+------+------
40 | 2 | 128 | 2
(1 row)
-- test unique index with not default value
ALTER TABLE t2 DROP CONSTRAINT t2_pkey;
CREATE UNIQUE INDEX t2_u_index ON t2(col2, col5);
SELECT col1, col2 FROM t1 WHERE col2 IS NOT NULL
EXCEPT
(SELECT col1, col3 FROM t1
UNION
SELECT NULL, NULL);
col1 | col2
------+------
1 | 2
(1 row)
INSERT INTO t2
SELECT col1, col2 FROM t1 WHERE col2 IS NOT NULL
EXCEPT
(SELECT col1, col3 FROM t1
UNION
SELECT NULL, NULL)
ON DUPLICATE KEY UPDATE col3 = (col1 + col2 + col3);
SELECT col1, col2, col3, col5 FROM t2 WHERE col2 = 2 ORDER BY col5, col2;
col1 | col2 | col3 | col5
------+------+------+------
40 | 2 | 128 | 2
1 | 2 | 1 | 46
(2 rows)
-- test t3 with one primary index with two columns
CREATE TABLE t3 (
col1 INT,
col2 INT,
col3 INT DEFAULT 1,
-- col4 TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
col5 BIGSERIAL,
PRIMARY KEY (col2, col3)
) ;
NOTICE: CREATE TABLE will create implicit sequence "t3_col5_seq" for serial column "t3.col5"
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "t3_pkey" for table "t3"
--- column referenced by primary key are not allowed to update
INSERT INTO t3 VALUES (1, 1) ON DUPLICATE KEY UPDATE col3 = 3;
ERROR: INSERT ON DUPLICATE KEY UPDATE don't allow update on primary key or unique key.
--- should insert when not contains primary key and not all primary key referred columns have default value.
--- but will fail cause primary key should not be null
INSERT INTO t3 (col1) VALUES (1) ON DUPLICATE KEY UPDATE col1 = 2;
ERROR: null value in column "col2" violates not-null constraint
--?.*
--- should insert
--- (SEQUENCE BUG: the serial column will starts from 2 since the above statement has applied for a sequence)
INSERT INTO t3 VALUES (1, 1) ON DUPLICATE KEY UPDATE col1 = 10;
INSERT INTO t3 VALUES (2, 2, 2) ON DUPLICATE KEY UPDATE col5 = 20;
SELECT * FROM t3 order by col5;
col1 | col2 | col3 | col5
------+------+------+------
1 | 1 | 1 | 2
2 | 2 | 2 | 3
(2 rows)
--- should update
INSERT INTO t3 VALUES (1, 1) ON DUPLICATE KEY UPDATE col1 = 10;
INSERT INTO t3 VALUES (2, 2, 2) ON DUPLICATE KEY UPDATE col5 = 20;
SELECT * FROM t3 order by col5;
col1 | col2 | col3 | col5
------+------+------+------
10 | 1 | 1 | 2
2 | 2 | 2 | 20
(2 rows)
--- test subquery
---- should insert
INSERT INTO t3 (col2, col3) (SELECT max(col2) + 1, max(col3) + 1 FROM t3) ON DUPLICATE KEY UPDATE col1 = col2 + col3;
SELECT * FROM t3 order by col5;
col1 | col2 | col3 | col5
------+------+------+------
10 | 1 | 1 | 2
| 3 | 3 | 6
2 | 2 | 2 | 20
(3 rows)
---- should update
INSERT INTO t3 (col2, col3) (SELECT max(col2), max(col3) FROM t3) ON DUPLICATE KEY UPDATE col1 = col2 + col3;
SELECT * FROM t3 order by col5;
col1 | col2 | col3 | col5
------+------+------+------
10 | 1 | 1 | 2
6 | 3 | 3 | 6
2 | 2 | 2 | 20
(3 rows)
-- test t3 with one unique index with two columns
TRUNCATE t3;
ALTER TABLE t3 DROP CONSTRAINT t3_pkey;
ALTER TABLE t3 ALTER COLUMN col2 DROP NOT NULL;
CREATE UNIQUE INDEX t3_ukey ON t3 (col2, col3);
--- column referenced by unique key are not allowed to update
INSERT INTO t3 VALUES (1, 1) ON DUPLICATE KEY UPDATE col3 = 3;
ERROR: INSERT ON DUPLICATE KEY UPDATE don't allow update on primary key or unique key.
--- should insert cause not contains unique key and not all unique key referred columns have default value.
INSERT INTO t3 (col1) VALUES (1) ON DUPLICATE KEY UPDATE col1 = 2;
INSERT INTO t3 (col1) VALUES (1) ON DUPLICATE KEY UPDATE col1 = 2;
SELECT * FROM t3 order by col5;
col1 | col2 | col3 | col5
------+------+------+------
1 | | 1 | 8
1 | | 1 | 9
(2 rows)
--- should insert
INSERT INTO t3 VALUES (1, 1) ON DUPLICATE KEY UPDATE col1 = 10;
INSERT INTO t3 VALUES (2, 2, 2) ON DUPLICATE KEY UPDATE t3.col5 = 20;
SELECT * FROM t3 ORDER BY col5;
col1 | col2 | col3 | col5
------+------+------+------
1 | | 1 | 8
1 | | 1 | 9
1 | 1 | 1 | 10
2 | 2 | 2 | 11
(4 rows)
--- should update
INSERT INTO t3 VALUES (1, 1) ON DUPLICATE KEY UPDATE t3.col1 = 10;
INSERT INTO t3 VALUES (2, 2, 2) ON DUPLICATE KEY UPDATE col5 = 20;
SELECT * FROM t3 ORDER BY col5;
col1 | col2 | col3 | col5
------+------+------+------
1 | | 1 | 8
1 | | 1 | 9
10 | 1 | 1 | 10
2 | 2 | 2 | 20
(4 rows)
--- test subquery
---- should insert
INSERT INTO t3 (SELECT 100, NULL, max(col3) FROM t3) ON DUPLICATE KEY UPDATE col1 = col2 + col3;
INSERT INTO t3 (SELECT 100, NULL, max(col3) FROM t3) ON DUPLICATE KEY UPDATE col1 = col2 + col3;
INSERT INTO t3 (col2, col3) (SELECT max(col2) + 1, max(col3) + 1 FROM t3) ON DUPLICATE KEY UPDATE col1 = col2 + col3;
SELECT * FROM t3 ORDER BY col5;
col1 | col2 | col3 | col5
------+------+------+------
1 | | 1 | 8
1 | | 1 | 9
10 | 1 | 1 | 10
100 | | 2 | 14
100 | | 2 | 15
| 3 | 3 | 16
2 | 2 | 2 | 20
(7 rows)
---- should update
INSERT INTO t3 (col2, col3) (SELECT max(col2), max(col3) FROM t3) ON DUPLICATE KEY UPDATE col1 = col2 + col3;
SELECT * FROM t3 ORDER BY col5;
col1 | col2 | col3 | col5
------+------+------+------
1 | | 1 | 8
1 | | 1 | 9
10 | 1 | 1 | 10
100 | | 2 | 14
100 | | 2 | 15
6 | 3 | 3 | 16
2 | 2 | 2 | 20
(7 rows)
RESET enable_light_proxy;
DROP SCHEMA test_insert_update_009 CASCADE;
NOTICE: drop cascades to 3 other objects
DETAIL: drop cascades to table t1
drop cascades to table t2
drop cascades to table t3

View File

@ -0,0 +1,313 @@
DROP SCHEMA test_insert_update_010 CASCADE;
ERROR: schema "test_insert_update_010" does not exist
CREATE SCHEMA test_insert_update_010;
SET CURRENT_SCHEMA TO test_insert_update_010;
-- enable_upsert_to_merge must is off, or upsert will be translated to merge.
SET enable_upsert_to_merge TO OFF;
-- test t4 with one primary key with three columns
CREATE TABLE t4 (
col1 INT,
col2 INT DEFAULT 0,
col3 INT DEFAULT 1,
col4 TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
col5 BIGSERIAL,
PRIMARY KEY (col2, col3, col5)
) ;
NOTICE: CREATE TABLE will create implicit sequence "t4_col5_seq" for serial column "t4.col5"
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "t4_pkey" for table "t4"
--- should insert
INSERT INTO t4 VALUES (1) ON DUPLICATE KEY UPDATE col1 = 10;
INSERT INTO t4 VALUES (1) ON DUPLICATE KEY UPDATE col1 = 10;
INSERT INTO t4 VALUES (2, 2, 2) ON DUPLICATE KEY UPDATE col1 = 200;
INSERT INTO t4 VALUES (100, 100, 100, CURRENT_TIMESTAMP, 100) ON DUPLICATE KEY UPDATE col1 = 1000;
SELECT col1, col2, col3, col5 FROM t4 ORDER BY col5;
col1 | col2 | col3 | col5
------+------+------+------
1 | 0 | 1 | 1
1 | 0 | 1 | 2
2 | 2 | 2 | 3
100 | 100 | 100 | 100
(4 rows)
--- should update
INSERT INTO t4 VALUES (2, 2, 2, CURRENT_TIMESTAMP, 3) ON DUPLICATE KEY UPDATE col1 = 200;
INSERT INTO t4 VALUES (100, 100, 100, CURRENT_TIMESTAMP, 100) ON DUPLICATE KEY UPDATE col1 = 1000;
SELECT col1, col2, col3, col5 FROM t4 ORDER BY col5;
col1 | col2 | col3 | col5
------+------+------+------
1 | 0 | 1 | 1
1 | 0 | 1 | 2
200 | 2 | 2 | 3
1000 | 100 | 100 | 100
(4 rows)
--- error: duplicate key update on (x, x, 20)
--- this is because current version is not inplace update but merge,
--- so when the subquery contains multiple same values, it will cause duplicate insert failure.
SELECT col3, sum(col3) * 10 FROM t4 GROUP BY col3 ORDER BY 1, 2;
col3 | ?column?
------+----------
1 | 20
2 | 20
100 | 1000
(3 rows)
INSERT INTO t4 (col1, col5)
(SELECT col3, sum(col3) * 10 FROM t4 GROUP BY col3)
ON DUPLICATE KEY UPDATE col1 = 3;
-- test t5 with sequence or default column with volatile function in constaint index
CREATE TABLE t5 (
col1 INT,
col2 INT DEFAULT 1,
col3 BIGSERIAL,
-- col4 TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
col5 INTEGER(10, 5) DEFAULT RANDOM() + 1
) ;
NOTICE: CREATE TABLE will create implicit sequence "t5_col3_seq" for serial column "t5.col3"
-- test t5 with sequence column in constaint index
CREATE UNIQUE INDEX u_t5_index1 ON t5(col1, col3);
--- should insert
INSERT INTO t5 VALUES (1), (1), (1) ON DUPLICATE KEY UPDATE col2 = col3;
INSERT INTO t5 DEFAULT VALUES ON DUPLICATE KEY UPDATE col2 = col3;
SELECT * FROM t5 ORDER BY col3;
col1 | col2 | col3 | col5
------+------+------+---------
--? 1 | 1 | 1 | 1.58182
--? 1 | 1 | 2 | 1.00814
--? 1 | 1 | 3 | 1.50194
--? | 1 | 4 | 1.12955
(4 rows)
--- should update
INSERT INTO t5 (col1, col3) VALUES (1, 1), (1, 2), (1, 3) ON DUPLICATE KEY UPDATE col5 = col2, col2 = col3 * 10;
SELECT * FROM t5 WHERE col1 = 1 ORDER BY col3;
col1 | col2 | col3 | col5
------+------+------+---------
1 | 10 | 1 | 1.00000
1 | 20 | 2 | 1.00000
1 | 30 | 3 | 1.00000
(3 rows)
--- should some insert some update
INSERT INTO t5 (col1, col3) VALUES (2, 5), (2, 6);
SELECT col1, col2, col3 FROM t5 ORDER BY col3;
col1 | col2 | col3
------+------+------
1 | 10 | 1
1 | 20 | 2
1 | 30 | 3
| 1 | 4
2 | 1 | 5
2 | 1 | 6
(6 rows)
INSERT INTO t5 (col1) VALUES (2), (2), (2) ON DUPLICATE KEY UPDATE col2 = col3;
SELECT col1, col2, col3 FROM t5 ORDER BY col3;
col1 | col2 | col3
------+------+------
1 | 10 | 1
1 | 20 | 2
1 | 30 | 3
| 1 | 4
2 | 5 | 5
2 | 6 | 6
2 | 1 | 7
(7 rows)
--- should INSERT and sequence starting from 7
INSERT INTO t5 VALUES (2), (2);
SELECT col1, col2, col3 FROM t5 ORDER BY col3;
col1 | col2 | col3
------+------+------
1 | 10 | 1
1 | 20 | 2
1 | 30 | 3
| 1 | 4
2 | 5 | 5
2 | 6 | 6
2 | 1 | 7
2 | 1 | 8
2 | 1 | 9
(9 rows)
-- test with volatile function as default column in constraint index
TRUNCATE t5;
DROP INDEX u_t5_index1;
CREATE UNIQUE INDEX u_t5_index2 ON t5(col1, col5) WHERE col1 > 2;
--- should insert
INSERT INTO t5 VALUES (3), (3), (3) ON DUPLICATE KEY UPDATE col2 = col3;
INSERT INTO t5 (col1) VALUES (4), (4), (4) ON DUPLICATE KEY UPDATE col2 = col3;
SELECT * FROM t5 ORDER BY col3;
col1 | col2 | col3 | col5
------+------+------+---------
--? 3 | 1 | 10 | 1.24521
--? 3 | 1 | 11 | 1.80598
--? 3 | 1 | 12 | 1.86845
--? 4 | 1 | 13 | 1.65797
--? 4 | 1 | 14 | 1.07881
--? 4 | 1 | 15 | 1.69493
(6 rows)
--- should update
INSERT INTO t5 (col1, col5) SELECT col1, col5 FROM t5 where col1 = 3 ON DUPLICATE KEY UPDATE col2 = col5 * 100;
SELECT * FROM t5 ORDER BY col3;
col1 | col2 | col3 | col5
------+------+------+---------
--? 3 | 125 | 10 | 1.24521
--? 3 | 181 | 11 | 1.80598
--? 3 | 187 | 12 | 1.86845
--? 4 | 1 | 13 | 1.65797
--? 4 | 1 | 14 | 1.07881
--? 4 | 1 | 15 | 1.69493
(6 rows)
--- test subquery
---- should insert
INSERT INTO t5 (col1, col2) SELECT col1, col2 FROM t5 ON DUPLICATE KEY UPDATE col2 = col5 * 100;
SELECT * FROM t5 ORDER BY col3;
col1 | col2 | col3 | col5
------+------+------+---------
--? 3 | 167 | 10 | 1.67400
--? 3 | 132 | 11 | 1.31552
--? 3 | 129 | 12 | 1.29423
--? 4 | 1 | 13 | 1.44100
--? 4 | 1 | 14 | 1.37620
--? 4 | 1 | 15 | 1.51296
--? 4 | 1 | 16 | 1.37516
--? 4 | 1 | 17 | 1.21710
--? 4 | 1 | 18 | 1.50422
--? 3 | 132 | 19 | 1.30560
--? 3 | 167 | 20 | 1.62282
--? 3 | 129 | 21 | 1.76699
(12 rows)
---- should update
INSERT INTO t5 SELECT * FROM t5 ON DUPLICATE KEY UPDATE col2 = col5 * 1000;
SELECT * FROM t5 ORDER BY col3;
col1 | col2 | col3 | col5
------+------+------+---------
--? 3 | 1674 | 10 | 1.67400
--? 3 | 1316 | 11 | 1.31552
--? 3 | 1294 | 12 | 1.29423
--? 4 | 1441 | 13 | 1.44100
--? 4 | 1376 | 14 | 1.37620
--? 4 | 1513 | 15 | 1.51296
--? 4 | 1375 | 16 | 1.37516
--? 4 | 1217 | 17 | 1.21710
--? 4 | 1504 | 18 | 1.50422
--? 3 | 1306 | 19 | 1.30560
--? 3 | 1623 | 20 | 1.62282
--? 3 | 1767 | 21 | 1.76699
(12 rows)
-- test t6 with one more index
CREATE TABLE t6 (
col1 INT,
col2 INT DEFAULT 1,
col3 BIGSERIAL,
-- col4 TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
col5 INTEGER(10, 5) DEFAULT RANDOM(),
col6 INT,
col7 TEXT
) ;
NOTICE: CREATE TABLE will create implicit sequence "t6_col3_seq" for serial column "t6.col3"
ALTER TABLE t6 ADD PRIMARY KEY (col1, col3);
NOTICE: ALTER TABLE / ADD PRIMARY KEY will create implicit index "t6_pkey" for table "t6"
CREATE UNIQUE INDEX u_t6_index1 ON t6(col1, col5, col6);
INSERT INTO t6 (col1) VALUES (1), (2), (3), (4), (5);
SELECT col1, col2, col3, col6, col7 FROM t6 ORDER BY col3;
col1 | col2 | col3 | col6 | col7
------+------+------+------+------
1 | 1 | 1 | |
2 | 1 | 2 | |
3 | 1 | 3 | |
4 | 1 | 4 | |
5 | 1 | 5 | |
(5 rows)
--- should insert
INSERT INTO t6 (col1) VALUES (1), (2), (3), (4), (5) ON DUPLICATE KEY UPDATE col6 = power(col1, col2);
ERROR: INSERT ON DUPLICATE KEY UPDATE don't allow update on primary key or unique key.
SELECT col1, col2, col3, col6, col7 FROM t6 ORDER BY col3;
col1 | col2 | col3 | col6 | col7
------+------+------+------+------
1 | 1 | 1 | |
2 | 1 | 2 | |
3 | 1 | 3 | |
4 | 1 | 4 | |
5 | 1 | 5 | |
(5 rows)
--- should update because primary key matches
INSERT INTO t6 (col1, col3) VALUES (6, 11), (6, 12);
SELECT col1, col2, col3, col6, col7 FROM t6 WHERE col1 = 6 ORDER BY col3;
col1 | col2 | col3 | col6 | col7
------+------+------+------+------
6 | 1 | 11 | |
6 | 1 | 12 | |
(2 rows)
INSERT INTO t6 (col1) VALUES (6), (6), (6) ON DUPLICATE KEY UPDATE col2 = col1 + col3, col6 = col2 * 10;
ERROR: INSERT ON DUPLICATE KEY UPDATE don't allow update on primary key or unique key.
SELECT col1, col2, col3, col6, col7 FROM t6 WHERE col1 = 6 ORDER BY col3;
col1 | col2 | col3 | col6 | col7
------+------+------+------+------
6 | 1 | 11 | |
6 | 1 | 12 | |
(2 rows)
--- should update for those col6 is not null bacause they will match the unique index,
--- and insert for those col6 is null because the unique index containing null never matches,
--- also primary key will not match
--- be ware the sequence column of the inserted row will jump n step, where n is the count of the not null rows,
--- because those sequence have to be generated during the unique index join stage.
INSERT INTO t6 (col1, col5, col6)
(SELECT col1, col5, col6 FROM t6 WHERE col1 = 6)
ON DUPLICATE KEY UPDATE
col7 = col2 + 1;
SELECT col1, col2, col3, col6, col7 FROM t6 WHERE col1 = 6 ORDER BY col1, col3, col6, col7;
col1 | col2 | col3 | col6 | col7
------+------+------+------+------
6 | 1 | 6 | |
6 | 1 | 7 | |
6 | 1 | 11 | |
6 | 1 | 12 | |
(4 rows)
--- should update because unique index and primary key both match
INSERT INTO t6 (col1, col3, col5, col6)
(SELECT col1, col3, col5, col6 FROM t6 WHERE col1 = 6 AND col6 IS NOT NULL)
ON DUPLICATE KEY UPDATE
col7 = col7 * 10;
SELECT col1, col2, col3, col6, col7 FROM t6 WHERE col1 = 6 ORDER BY col1, col3, col6, col7;
col1 | col2 | col3 | col6 | col7
------+------+------+------+------
6 | 1 | 6 | |
6 | 1 | 7 | |
6 | 1 | 11 | |
6 | 1 | 12 | |
(4 rows)
--- insert when col3 = 17 because constaints does not match,
--- but update when col3 = 18 because 18 has been inserted and will cause a match
INSERT INTO t6 (col1, col3, col5, col6) VALUES (7, 18, 100, 100);
SELECT * FROM t6 WHERE col3 > 16 ORDER BY col1, col3, col6, col7;
col1 | col2 | col3 | col5 | col6 | col7
------+------+------+-----------+------+------
7 | 1 | 18 | 100.00000 | 100 |
(1 row)
INSERT INTO t6 (col1, col5, col6) VALUES (7, 10, 10), (7, 100, 100) ON DUPLICATE KEY UPDATE
col7 = col3 * 100;
SELECT * FROM t6 WHERE col1 = 7 ORDER BY col1, col3, col6, col7;
col1 | col2 | col3 | col5 | col6 | col7
------+------+------+-----------+------+------
7 | 1 | 8 | 10.00000 | 10 |
7 | 1 | 18 | 100.00000 | 100 | 1800
(2 rows)
DROP SCHEMA test_insert_update_010 CASCADE;
NOTICE: drop cascades to 3 other objects
DETAIL: drop cascades to table t4
drop cascades to table t5
drop cascades to table t6

View File

@ -0,0 +1,19 @@
\c upsert
DROP SCHEMA upsert_test CASCADE;
NOTICE: drop cascades to 8 other objects
DETAIL: drop cascades to type upsert_test.atype
drop cascades to type upsert_test.btype
drop cascades to table upsert_test.t_grammer
drop cascades to table upsert_test.t_default
drop cascades to table upsert_test.t_data
drop cascades to table upsert_test.t_trigger
drop cascades to function upsert_test.upsert_before_func()
drop cascades to function upsert_test.upsert_after_func()
DROP SCHEMA upsert_test_unlog CASCADE;
NOTICE: drop cascades to 6 other objects
DETAIL: drop cascades to type upsert_test_unlog.atype
drop cascades to type upsert_test_unlog.btype
drop cascades to table upsert_test_unlog.t_hash_unlog_0
drop cascades to table upsert_test_unlog.t_hash_unlog_1
drop cascades to table upsert_test_unlog.t_rep_unlog_0
drop cascades to table upsert_test_unlog.t_rep_unlog_1

View File

@ -0,0 +1 @@
drop database upsert_etc;

View File

@ -0,0 +1,404 @@
--------------------------------------------------------------------------------------------
/*
* procedure
*/
--------------------------------------------------------------------------------------------
\c upsert;
SET CURRENT_SCHEMA TO upsert_test_procedure;
-- enable_upsert_to_merge must be off, or upsert will be translated to merge.
SET enable_upsert_to_merge TO OFF;
SHOW enable_upsert_to_merge;
enable_upsert_to_merge
------------------------
off
(1 row)
drop table IF EXISTS t_proc;
NOTICE: table "t_proc" does not exist, skipping
create table t_proc(c1 int, c2 int, c3 int unique);
NOTICE: CREATE TABLE / UNIQUE will create implicit index "t_proc_c3_key" for table "t_proc"
insert into t_proc select a,a,a from generate_series(1,20) as a;
select *from t_proc order by c3;
c1 | c2 | c3
----+----+----
1 | 1 | 1
2 | 2 | 2
3 | 3 | 3
4 | 4 | 4
5 | 5 | 5
6 | 6 | 6
7 | 7 | 7
8 | 8 | 8
9 | 9 | 9
10 | 10 | 10
11 | 11 | 11
12 | 12 | 12
13 | 13 | 13
14 | 14 | 14
15 | 15 | 15
16 | 16 | 16
17 | 17 | 17
18 | 18 | 18
19 | 19 | 19
20 | 20 | 20
(20 rows)
create or replace procedure mul_ups( c in INTEGER)
as
declare
val int;
begin
for val in select c3 from t_proc loop
insert into t_proc values(c,c, val) on duplicate key update c1 = c, c2 =c;
end loop;
end;
/
call mul_ups(100);
mul_ups
---------
(1 row)
select *from t_proc order by c3;
c1 | c2 | c3
-----+-----+----
100 | 100 | 1
100 | 100 | 2
100 | 100 | 3
100 | 100 | 4
100 | 100 | 5
100 | 100 | 6
100 | 100 | 7
100 | 100 | 8
100 | 100 | 9
100 | 100 | 10
100 | 100 | 11
100 | 100 | 12
100 | 100 | 13
100 | 100 | 14
100 | 100 | 15
100 | 100 | 16
100 | 100 | 17
100 | 100 | 18
100 | 100 | 19
100 | 100 | 20
(20 rows)
create or replace procedure mul_ups( c in INTEGER)
as
declare
val int;
begin
for val in select c3 from t_proc loop
insert into t_proc values(c,c, val) on duplicate key update c1 = $1, c2 =$1;
end loop;
end;
/
call mul_ups(200);
mul_ups
---------
(1 row)
select *from t_proc order by c3;
c1 | c2 | c3
-----+-----+----
200 | 200 | 1
200 | 200 | 2
200 | 200 | 3
200 | 200 | 4
200 | 200 | 5
200 | 200 | 6
200 | 200 | 7
200 | 200 | 8
200 | 200 | 9
200 | 200 | 10
200 | 200 | 11
200 | 200 | 12
200 | 200 | 13
200 | 200 | 14
200 | 200 | 15
200 | 200 | 16
200 | 200 | 17
200 | 200 | 18
200 | 200 | 19
200 | 200 | 20
(20 rows)
create or replace procedure mul_ups_00()
as
declare
val int;
begin
for val in select c3 from t_proc loop
insert into t_proc values(val,val,val) on duplicate key update c1 = 300, c2 =300;
end loop;
end;
/
call mul_ups_00();
mul_ups_00
------------
(1 row)
select *from t_proc order by c3;
c1 | c2 | c3
-----+-----+----
300 | 300 | 1
300 | 300 | 2
300 | 300 | 3
300 | 300 | 4
300 | 300 | 5
300 | 300 | 6
300 | 300 | 7
300 | 300 | 8
300 | 300 | 9
300 | 300 | 10
300 | 300 | 11
300 | 300 | 12
300 | 300 | 13
300 | 300 | 14
300 | 300 | 15
300 | 300 | 16
300 | 300 | 17
300 | 300 | 18
300 | 300 | 19
300 | 300 | 20
(20 rows)
declare
val int;
c int :=400;
begin
for val in select c3 from t_proc loop
insert into t_proc values(c,c, val) on duplicate key update c1 = c, c2 =c;
end loop;
end;
/
select *from t_proc order by c3;
c1 | c2 | c3
-----+-----+----
400 | 400 | 1
400 | 400 | 2
400 | 400 | 3
400 | 400 | 4
400 | 400 | 5
400 | 400 | 6
400 | 400 | 7
400 | 400 | 8
400 | 400 | 9
400 | 400 | 10
400 | 400 | 11
400 | 400 | 12
400 | 400 | 13
400 | 400 | 14
400 | 400 | 15
400 | 400 | 16
400 | 400 | 17
400 | 400 | 18
400 | 400 | 19
400 | 400 | 20
(20 rows)
create or replace procedure mul_ups( c in INTEGER)
as
declare
val int;
begin
for val in select c3 from t_proc loop
insert into t_proc values(c,c, val+100) on duplicate key update c1 = $1, c2 =$1;
end loop;
end;
/
call mul_ups(500);
mul_ups
---------
(1 row)
select *from t_proc order by c3;
c1 | c2 | c3
-----+-----+-----
400 | 400 | 1
400 | 400 | 2
400 | 400 | 3
400 | 400 | 4
400 | 400 | 5
400 | 400 | 6
400 | 400 | 7
400 | 400 | 8
400 | 400 | 9
400 | 400 | 10
400 | 400 | 11
400 | 400 | 12
400 | 400 | 13
400 | 400 | 14
400 | 400 | 15
400 | 400 | 16
400 | 400 | 17
400 | 400 | 18
400 | 400 | 19
400 | 400 | 20
500 | 500 | 101
500 | 500 | 102
500 | 500 | 103
500 | 500 | 104
500 | 500 | 105
500 | 500 | 106
500 | 500 | 107
500 | 500 | 108
500 | 500 | 109
500 | 500 | 110
500 | 500 | 111
500 | 500 | 112
500 | 500 | 113
500 | 500 | 114
500 | 500 | 115
500 | 500 | 116
500 | 500 | 117
500 | 500 | 118
500 | 500 | 119
500 | 500 | 120
(40 rows)
/*
* insert
*/
drop table if exists t_default;
NOTICE: table "t_default" does not exist, skipping
CREATE TABLE t_default (c1 INT PRIMARY KEY DEFAULT 10, c2 FLOAT DEFAULT 3.0, c3 TIMESTAMP DEFAULT '20200508');
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "t_default_pkey" for table "t_default"
create view v_default as select *from t_default order by c1;
-- insert src
---- insert values
truncate t_default;
insert into t_default values(DEFAULT, DEFAULT, DEFAULT);
insert into t_default values(1, 2, '20200630');
select *from t_default order by c1;
c1 | c2 | c3
----+----+--------------------------
1 | 2 | Tue Jun 30 00:00:00 2020
10 | 3 | Fri May 08 00:00:00 2020
(2 rows)
insert into t_default values(DEFAULT, DEFAULT, DEFAULT) on duplicate key update c2 = 1;
select *from t_default order by c1;
c1 | c2 | c3
----+----+--------------------------
1 | 2 | Tue Jun 30 00:00:00 2020
10 | 1 | Fri May 08 00:00:00 2020
(2 rows)
insert into t_default values(1, 2, '20200630') on duplicate key update c2 = 2;
select *from t_default order by c1;
c1 | c2 | c3
----+----+--------------------------
1 | 2 | Tue Jun 30 00:00:00 2020
10 | 1 | Fri May 08 00:00:00 2020
(2 rows)
insert into t_default values(DEFAULT, DEFAULT, DEFAULT),(1, 2, '20200630') on duplicate key update c2 = 3;
select *from t_default order by c1;
c1 | c2 | c3
----+----+--------------------------
1 | 3 | Tue Jun 30 00:00:00 2020
10 | 3 | Fri May 08 00:00:00 2020
(2 rows)
---- insert subquery
insert into t_default select *from t_default order by c1 on duplicate key update c2 = 4;
select *from t_default order by c1;
c1 | c2 | c3
----+----+--------------------------
1 | 4 | Tue Jun 30 00:00:00 2020
10 | 4 | Fri May 08 00:00:00 2020
(2 rows)
insert into t_default select *from t_default order by c1 limit 1 on duplicate key update c2 = 5;
select *from t_default order by c1;
c1 | c2 | c3
----+----+--------------------------
1 | 5 | Tue Jun 30 00:00:00 2020
10 | 4 | Fri May 08 00:00:00 2020
(2 rows)
insert into t_default select *from t_default where c1=10 on duplicate key update c2 = 6;
select *from t_default order by c1;
c1 | c2 | c3
----+----+--------------------------
1 | 5 | Tue Jun 30 00:00:00 2020
10 | 6 | Fri May 08 00:00:00 2020
(2 rows)
insert into t_default select *from t_default order by c1 on duplicate key update c2 = 7;
select *from t_default order by c1;
c1 | c2 | c3
----+----+--------------------------
1 | 7 | Tue Jun 30 00:00:00 2020
10 | 7 | Fri May 08 00:00:00 2020
(2 rows)
insert into t_default select *from v_default order by c1 on duplicate key update c2 = 8;
select *from t_default order by c1;
c1 | c2 | c3
----+----+--------------------------
1 | 8 | Tue Jun 30 00:00:00 2020
10 | 8 | Fri May 08 00:00:00 2020
(2 rows)
insert into t_default select *from t_default union select c1+1,c2+1,c3+1 from t_default order by c1 on duplicate key update c2 = 9;
select *from t_default order by c1;
c1 | c2 | c3
----+----+--------------------------
1 | 9 | Tue Jun 30 00:00:00 2020
2 | 9 | Wed Jul 01 00:00:00 2020
10 | 9 | Fri May 08 00:00:00 2020
11 | 9 | Sat May 09 00:00:00 2020
(4 rows)
insert into t_default(c1,c2) select max(c1),c2 from t_default group by c2 on duplicate key update c2 = 10;
-- index
---- mul index
truncate t_default;
create unique index t_default_mul on t_default(c1,c3);
insert into t_default values(DEFAULT, DEFAULT, DEFAULT);
insert into t_default values(1, 2, '20200630');
select *from t_default order by c1;
c1 | c2 | c3
----+----+--------------------------
1 | 2 | Tue Jun 30 00:00:00 2020
10 | 3 | Fri May 08 00:00:00 2020
(2 rows)
insert into t_default values(DEFAULT, DEFAULT, DEFAULT) on duplicate key update c2 = 1;
select *from t_default order by c1;
c1 | c2 | c3
----+----+--------------------------
1 | 2 | Tue Jun 30 00:00:00 2020
10 | 1 | Fri May 08 00:00:00 2020
(2 rows)
insert into t_default values(1, 2, '20200630') on duplicate key update c2 = 2;
select *from t_default order by c1;
c1 | c2 | c3
----+----+--------------------------
1 | 2 | Tue Jun 30 00:00:00 2020
10 | 1 | Fri May 08 00:00:00 2020
(2 rows)
insert into t_default values(DEFAULT, DEFAULT, DEFAULT),(1, 2, '20200630') on duplicate key update c2 = 3;
select *from t_default order by c1;
c1 | c2 | c3
----+----+--------------------------
1 | 3 | Tue Jun 30 00:00:00 2020
10 | 3 | Fri May 08 00:00:00 2020
(2 rows)
insert into t_default select *from t_default on duplicate key update c2 = 4;
select *from t_default order by c1;
c1 | c2 | c3
----+----+--------------------------
1 | 4 | Tue Jun 30 00:00:00 2020
10 | 4 | Fri May 08 00:00:00 2020
(2 rows)

View File

@ -0,0 +1,297 @@
--------------------------------------------------------------------------------------------
/*
* explain upsert
*/
--------------------------------------------------------------------------------------------
\c upsert;
SET CURRENT_SCHEMA TO upsert_test_explain;
-- enable_upsert_to_merge must be off, or upsert will be translated to merge.
SET enable_upsert_to_merge TO OFF;
SHOW enable_upsert_to_merge;
enable_upsert_to_merge
------------------------
off
(1 row)
create temp table up_expl_temp(c1 int, c2 int, c3 int unique) ;
NOTICE: CREATE TABLE / UNIQUE will create implicit index "up_expl_temp_c3_key" for table "up_expl_temp"
insert into up_expl_hash select a,a,a from generate_series(1,20) as a;
insert into up_expl_repl select a,a,a from generate_series(1,20) as a;
insert into up_expl_part select a,a,a from generate_series(1,20) as a;
insert into up_expl_temp select a,a,a from generate_series(1,20) as a;
insert into up_expl_unlog select a,a,a from generate_series(1,20) as a;
insert into up_expl_node select a,a,a from generate_series(1,20) as a;
insert into up_expl_repl2 select a,a,a,a,a from generate_series(1,20) as a;
EXPLAIN (VERBOSE on, COSTS off, TIMING off) insert into up_expl_hash values(1,1,1) on duplicate key update c1 = 2;
QUERY PLAN
-------------------------------------------------
Insert on upsert_test_explain.up_expl_hash
Conflict Resolution: UPDATE
Conflict Arbiter Indexes: up_expl_hash_c3_key
-> Result
Output: 1, 1, 1
(5 rows)
EXPLAIN (ANALYZE on, COSTS off, TIMING off) insert into up_expl_hash values(1,1,1) on duplicate key update c1 = 2;
QUERY PLAN
-------------------------------------------------
Insert on up_expl_hash (actual rows=1 loops=1)
Conflict Resolution: UPDATE
Conflict Arbiter Indexes: up_expl_hash_c3_key
-> Result (actual rows=1 loops=1)
--? Total runtime: .* ms
(5 rows)
EXPLAIN PERFORMANCE insert into up_expl_hash values(1,1,1) on duplicate key update c1 = 2;
QUERY PLAN
------------------------------------------------------------------------------------------------------------------------
--? Insert on upsert_test_explain.up_expl_hash (cost=.* rows=1 width=0) (actual time=.* rows=1 loops=1)
Conflict Resolution: UPDATE
Conflict Arbiter Indexes: up_expl_hash_c3_key
(Buffers: shared hit=4)
--? (CPU: ex c/r=.*, ex row=1, ex cyc=.*, inc cyc=.*)
--? -> Result (cost=.* rows=1 width=0) (actual time=.* rows=1 loops=1)
Output: 1, 1, 1
--? (CPU: ex c/r=.*, ex row=1, ex cyc=.*, inc cyc=.*)
--? Total runtime: .* ms
(9 rows)
EXPLAIN (VERBOSE on, COSTS off, TIMING off) insert into up_expl_hash values(1,1,1),(2,2,2)on duplicate key update c1 = 2;
QUERY PLAN
----------------------------------------------------------------------------
Insert on upsert_test_explain.up_expl_hash
Conflict Resolution: UPDATE
Conflict Arbiter Indexes: up_expl_hash_c3_key
-> Values Scan on "*VALUES*"
Output: "*VALUES*".column1, "*VALUES*".column2, "*VALUES*".column3
(5 rows)
EXPLAIN (ANALYZE on, COSTS off, TIMING off) insert into up_expl_hash values(1,1,1),(2,2,2)on duplicate key update c1 = 2;
QUERY PLAN
---------------------------------------------------------
Insert on up_expl_hash (actual rows=2 loops=1)
Conflict Resolution: UPDATE
Conflict Arbiter Indexes: up_expl_hash_c3_key
-> Values Scan on "*VALUES*" (actual rows=2 loops=1)
--? Total runtime: .* ms
(5 rows)
EXPLAIN (VERBOSE on, COSTS off, TIMING off) insert into up_expl_repl values(1,1,1) on duplicate key update c1 = 2;
QUERY PLAN
-------------------------------------------------
Insert on upsert_test_explain.up_expl_repl
Conflict Resolution: UPDATE
Conflict Arbiter Indexes: up_expl_repl_c3_key
-> Result
Output: 1, 1, 1
(5 rows)
EXPLAIN (ANALYZE on, COSTS off, TIMING off) insert into up_expl_repl values(1,1,1) on duplicate key update c1 = 2;
QUERY PLAN
-------------------------------------------------
Insert on up_expl_repl (actual rows=1 loops=1)
Conflict Resolution: UPDATE
Conflict Arbiter Indexes: up_expl_repl_c3_key
-> Result (actual rows=1 loops=1)
--? Total runtime: .* ms
(5 rows)
EXPLAIN (VERBOSE on, COSTS off, TIMING off) insert into up_expl_part values(1,1,1) on duplicate key update c1 = 2;
QUERY PLAN
-------------------------------------------------
Insert on upsert_test_explain.up_expl_part
Conflict Resolution: UPDATE
Conflict Arbiter Indexes: up_expl_part_c3_key
-> Result
Output: 1, 1, 1
(5 rows)
EXPLAIN (ANALYZE on, COSTS off, TIMING off) insert into up_expl_part values(1,1,1) on duplicate key update c1 = 2;
QUERY PLAN
-------------------------------------------------
Insert on up_expl_part (actual rows=1 loops=1)
Conflict Resolution: UPDATE
Conflict Arbiter Indexes: up_expl_part_c3_key
-> Result (actual rows=1 loops=1)
--? Total runtime: .* ms
(5 rows)
EXPLAIN (VERBOSE on, COSTS off, TIMING off) insert into up_expl_temp values(1,1,1) on duplicate key update c1 = 2;
QUERY PLAN
--?.*
--? Insert on pg_temp_datanod.*.up_expl_temp
Conflict Resolution: UPDATE
Conflict Arbiter Indexes: up_expl_temp_c3_key
-> Result
Output: 1, 1, 1
(5 rows)
EXPLAIN (ANALYZE on, COSTS off, TIMING off) insert into up_expl_temp values(1,1,1) on duplicate key update c1 = 2;
QUERY PLAN
-------------------------------------------------
Insert on up_expl_temp (actual rows=1 loops=1)
Conflict Resolution: UPDATE
Conflict Arbiter Indexes: up_expl_temp_c3_key
-> Result (actual rows=1 loops=1)
--? Total runtime: .* ms
(5 rows)
EXPLAIN (VERBOSE on, COSTS off, TIMING off) insert into up_expl_unlog values(1,1,1) on duplicate key update c1 = 2;
QUERY PLAN
--------------------------------------------------
Insert on upsert_test_explain.up_expl_unlog
Conflict Resolution: UPDATE
Conflict Arbiter Indexes: up_expl_unlog_c3_key
-> Result
Output: 1, 1, 1
(5 rows)
EXPLAIN (ANALYZE on, COSTS off, TIMING off) insert into up_expl_unlog values(1,1,1) on duplicate key update c1 = 2;
QUERY PLAN
--------------------------------------------------
Insert on up_expl_unlog (actual rows=1 loops=1)
Conflict Resolution: UPDATE
Conflict Arbiter Indexes: up_expl_unlog_c3_key
-> Result (actual rows=1 loops=1)
--? Total runtime: .* ms
(5 rows)
EXPLAIN (VERBOSE on, COSTS off, TIMING off) insert into up_expl_node values(1,1,1) on duplicate key update c1 = 2;
QUERY PLAN
-------------------------------------------------
Insert on upsert_test_explain.up_expl_node
Conflict Resolution: UPDATE
Conflict Arbiter Indexes: up_expl_node_c3_key
-> Result
Output: 1, 1, 1
(5 rows)
EXPLAIN (ANALYZE on, COSTS off, TIMING off) insert into up_expl_node values(1,1,1) on duplicate key update c1 = 2;
QUERY PLAN
-------------------------------------------------
Insert on up_expl_node (actual rows=1 loops=1)
Conflict Resolution: UPDATE
Conflict Arbiter Indexes: up_expl_node_c3_key
-> Result (actual rows=1 loops=1)
--? Total runtime: .* ms
(5 rows)
EXPLAIN (VERBOSE on, COSTS off, TIMING off) insert into up_expl_hash values(1,1,1),(2,2,2)on duplicate key update nothing;
QUERY PLAN
----------------------------------------------------------------------------
Insert on upsert_test_explain.up_expl_hash
Conflict Resolution: NOTHING
Conflict Arbiter Indexes: up_expl_hash_c3_key
-> Values Scan on "*VALUES*"
Output: "*VALUES*".column1, "*VALUES*".column2, "*VALUES*".column3
(5 rows)
EXPLAIN (ANALYZE on, COSTS off, TIMING off) insert into up_expl_hash values(1,1,1),(2,2,2)on duplicate key update nothing;
QUERY PLAN
---------------------------------------------------------
Insert on up_expl_hash (actual rows=0 loops=1)
Conflict Resolution: NOTHING
Conflict Arbiter Indexes: up_expl_hash_c3_key
-> Values Scan on "*VALUES*" (actual rows=2 loops=1)
--? Total runtime: .* ms
(5 rows)
EXPLAIN (VERBOSE on, COSTS off, TIMING off) insert into up_expl_repl values(1,1,1) on duplicate key update nothing;
QUERY PLAN
-------------------------------------------------
Insert on upsert_test_explain.up_expl_repl
Conflict Resolution: NOTHING
Conflict Arbiter Indexes: up_expl_repl_c3_key
-> Result
Output: 1, 1, 1
(5 rows)
EXPLAIN (ANALYZE on, COSTS off, TIMING off) insert into up_expl_repl values(1,1,1) on duplicate key update nothing;
QUERY PLAN
-------------------------------------------------
Insert on up_expl_repl (actual rows=0 loops=1)
Conflict Resolution: NOTHING
Conflict Arbiter Indexes: up_expl_repl_c3_key
-> Result (actual rows=1 loops=1)
--? Total runtime: .* ms
(5 rows)
EXPLAIN (VERBOSE on, COSTS off, TIMING off) insert into up_expl_part values(1,1,1) on duplicate key update nothing;
QUERY PLAN
-------------------------------------------------
Insert on upsert_test_explain.up_expl_part
Conflict Resolution: NOTHING
Conflict Arbiter Indexes: up_expl_part_c3_key
-> Result
Output: 1, 1, 1
(5 rows)
EXPLAIN (ANALYZE on, COSTS off, TIMING off) insert into up_expl_part values(1,1,1) on duplicate key update nothing;
QUERY PLAN
-------------------------------------------------
Insert on up_expl_part (actual rows=0 loops=1)
Conflict Resolution: NOTHING
Conflict Arbiter Indexes: up_expl_part_c3_key
-> Result (actual rows=1 loops=1)
--? Total runtime: .* ms
(5 rows)
EXPLAIN (VERBOSE on, COSTS off, TIMING off) insert into up_expl_temp values(1,1,1) on duplicate key update nothing;
QUERY PLAN
--?.*
--? Insert on pg_temp_datanod.*.up_expl_temp
Conflict Resolution: NOTHING
Conflict Arbiter Indexes: up_expl_temp_c3_key
-> Result
Output: 1, 1, 1
(5 rows)
EXPLAIN (ANALYZE on, COSTS off, TIMING off) insert into up_expl_temp values(1,1,1) on duplicate key update nothing;
QUERY PLAN
-------------------------------------------------
Insert on up_expl_temp (actual rows=0 loops=1)
Conflict Resolution: NOTHING
Conflict Arbiter Indexes: up_expl_temp_c3_key
-> Result (actual rows=1 loops=1)
--? Total runtime: .* ms
(5 rows)
EXPLAIN (VERBOSE on, COSTS off, TIMING off) insert into up_expl_unlog values(1,1,1) on duplicate key update nothing;
QUERY PLAN
--------------------------------------------------
Insert on upsert_test_explain.up_expl_unlog
Conflict Resolution: NOTHING
Conflict Arbiter Indexes: up_expl_unlog_c3_key
-> Result
Output: 1, 1, 1
(5 rows)
EXPLAIN (ANALYZE on, COSTS off, TIMING off) insert into up_expl_unlog values(1,1,1) on duplicate key update nothing;
QUERY PLAN
--------------------------------------------------
Insert on up_expl_unlog (actual rows=0 loops=1)
Conflict Resolution: NOTHING
Conflict Arbiter Indexes: up_expl_unlog_c3_key
-> Result (actual rows=1 loops=1)
--? Total runtime: .* ms
(5 rows)
EXPLAIN (VERBOSE on, COSTS off, TIMING off) insert into up_expl_node values(1,1,1) on duplicate key update nothing;
QUERY PLAN
-------------------------------------------------
Insert on upsert_test_explain.up_expl_node
Conflict Resolution: NOTHING
Conflict Arbiter Indexes: up_expl_node_c3_key
-> Result
Output: 1, 1, 1
(5 rows)
EXPLAIN (ANALYZE on, COSTS off, TIMING off) insert into up_expl_node values(1,1,1) on duplicate key update nothing;
QUERY PLAN
-------------------------------------------------
Insert on up_expl_node (actual rows=0 loops=1)
Conflict Resolution: NOTHING
Conflict Arbiter Indexes: up_expl_node_c3_key
-> Result (actual rows=1 loops=1)
--? Total runtime: .* ms
(5 rows)

View File

@ -0,0 +1,188 @@
\c upsert
SET CURRENT_SCHEMA TO upsert_test;
-- enable_upsert_to_merge must be off, or upsert will be translated to merge.
SET enable_upsert_to_merge TO OFF;
SHOW enable_upsert_to_merge;
enable_upsert_to_merge
------------------------
off
(1 row)
-- support multiple set
INSERT INTO t_grammer VALUES(11, 1) ON DUPLICATE KEY UPDATE c2 = 2, c4 = ROW(10, 20), c3 = '{10, 20, 30}';
INSERT INTO t_grammer VALUES(12, 2) ON DUPLICATE KEY UPDATE c2 = 2, c3[1] = 3;
-- support const value and expr
INSERT INTO t_grammer VALUES(23) ON DUPLICATE KEY UPDATE c2 = 2;
INSERT INTO t_grammer VALUES(24) ON DUPLICATE KEY UPDATE c2 = length('test') + 100;
-- support without table name
INSERT INTO t_grammer VALUES(31, 1) ON DUPLICATE KEY UPDATE c2 = c1, c4.a = VALUES(c1);
INSERT INTO t_grammer VALUES(32, 2) ON DUPLICATE KEY UPDATE c2 = c1 + 5, c4.a = VALUES(c1);
-- support with table name
INSERT INTO t_grammer VALUES(41, 1) ON DUPLICATE KEY UPDATE c2 = t_grammer.c1, c4.a = VALUES(c1);
INSERT INTO t_grammer VALUES(42, 2) ON DUPLICATE KEY UPDATE c2 = t_grammer.c1 + 5, c4.a = VALUES(c1);
-- support EXCLUDED alone and with expr
INSERT INTO t_grammer VALUES(51, 1) ON DUPLICATE KEY UPDATE c2 = c1 + 5, c4.a = EXCLUDED.c1;
INSERT INTO t_grammer VALUES(52, 2) ON DUPLICATE KEY UPDATE c2 = t_grammer.c1 + 5, c4.a = EXCLUDED.c1 + 5;
INSERT INTO t_grammer VALUES(53, 3) ON DUPLICATE KEY UPDATE c4.a = sqrt(EXCLUDED.c1 - EXCLUDED.c2 - 1) + 1, c2 = t_grammer.c1 + 5;
INSERT INTO t_grammer VALUES(54, 4) ON DUPLICATE KEY UPDATE c4.b = EXCLUDED.c1 + t_grammer.c1;
INSERT INTO t_grammer VALUES(55, 5) ON DUPLICATE KEY UPDATE c4.a = EXCLUDED.c2, c4.b = EXCLUDED.c1 + sqrt(c1 - 6);
-- support ARRAY
INSERT INTO t_grammer VALUES(61, 1) ON DUPLICATE KEY UPDATE c2 = VALUES(c3[1]);
INSERT INTO t_grammer VALUES(62, 2) ON DUPLICATE KEY UPDATE c5 = VALUES(c3[2,3]);
INSERT INTO t_grammer VALUES(63, 3) ON DUPLICATE KEY UPDATE c5 = VALUES(c3[2:3]);
INSERT INTO t_grammer VALUES(64, 4, '{10, 20, 30}') ON DUPLICATE KEY UPDATE c2 = EXCLUDED.c3[1];
INSERT INTO t_grammer VALUES(65, 5, '{10, 20, 30}') ON DUPLICATE KEY UPDATE c5 = EXCLUDED.c3[2,3];
INSERT INTO t_grammer VALUES(66, 6, '{10, 20, 30}') ON DUPLICATE KEY UPDATE c5 = EXCLUDED.c3[1:2];
INSERT INTO t_grammer VALUES(67, 7, '{10, 20, 30}') ON DUPLICATE KEY UPDATE c2 = c3[1];
INSERT INTO t_grammer VALUES(68, 8, '{10, 20, 30}') ON DUPLICATE KEY UPDATE c5 = c3[2,3];
INSERT INTO t_grammer VALUES(69, 9, '{10, 20, 30}') ON DUPLICATE KEY UPDATE c5 = c3[1:2];
-- support user defined type
INSERT INTO t_grammer VALUES(71, 1) ON DUPLICATE KEY UPDATE c4.a = c3[1] + c1;
INSERT INTO t_grammer VALUES(72, 2, '{71, 72, 73}') ON DUPLICATE KEY UPDATE c4.a = c3[1] + c1;
INSERT INTO t_grammer VALUES(73, 3, '{71, 72, 73}') ON DUPLICATE KEY UPDATE c4.a = c3[1] + c1, c4.b = c3[2];
INSERT INTO t_grammer VALUES(74, 4, '{71, 72, 73}', ROW(74, 75)) ON DUPLICATE KEY UPDATE c4 = ROW(740, 750);
-- appoint INSERT target column
INSERT INTO t_grammer (c5, c1, c2) VALUES('{81,82}', 81, DEFAULT) ON DUPLICATE KEY UPDATE c2 = VALUES(c1);
INSERT INTO t_grammer (c3[1], c3[2], c1) VALUES(881, 882, 82) ON DUPLICATE KEY UPDATE c5 = VALUES(c3), c2 = VALUES(c3[1]);
INSERT INTO t_grammer (c1, c3, c4) VALUES(83, '{81, 82, 83}', ROW(810, 820)) ON DUPLICATE KEY UPDATE c4 = EXCLUDED.c4;
INSERT INTO t_grammer (c1, c3, c4.a) VALUES(84, '{81, 82, 83}', 850) ON DUPLICATE KEY UPDATE c4.b = c3[3];
-- support UPDATE NOTHING
INSERT INTO t_grammer VALUES(91, 1, '{91, 92, 93}', ROW(94, 95)) ON DUPLICATE KEY UPDATE NOTHING;
INSERT INTO t_grammer (c5, c1, c2, c4) VALUES('{91,92}', 92, DEFAULT, ROW(910, 920)) ON DUPLICATE KEY UPDATE NOTHING;
-- UPDATE target: unsupport with schema but support with tablename
INSERT INTO t_grammer VALUES(0, 0, '{0,0}', ROW(0, 0), '{107, 108}') ON DUPLICATE KEY UPDATE
upsert_test.t_grammer.c2 = c2 * 10, upsert_test.t_grammer.c3[1:2] = c5[1:2], upsert_test.t_grammer.c4.a = c1;
ERROR: column "upsert_test.t_grammer" of relation "t_grammer" does not exist
LINE 2: upsert_test.t_grammer.c2 = c2 * 10, upsert_test.t_grammer.c...
^
INSERT INTO t_grammer VALUES(101, 1, '{102, 103, 104}', ROW(105, 106), '{107, 108}') ON DUPLICATE KEY UPDATE
t_grammer.c2 = c2 * 10, t_grammer.c3[1:2] = c5[1:2], t_grammer.c4.a = c1;
-- INSERT target: appoint schema
INSERT INTO upsert_test.t_grammer VALUES(102, 2, '{102, 103, 104}', ROW(105, 106), '{107, 108}') ON DUPLICATE KEY UPDATE
t_grammer.c2 = EXCLUDED.c2 * 10, t_grammer.c3[1:2] = c5[1:2], t_grammer.c4.a = VALUES(c1);
CREATE SCHEMA upsert_test_tmpschema;
SET CURRENT_SCHEMA TO upsert_test_tmpschema;
INSERT INTO upsert_test.t_grammer VALUES(103, 3, '{102, 103, 104}', ROW(105, 106), '{107, 108}') ON DUPLICATE KEY UPDATE
t_grammer.c2 = EXCLUDED.c2 * 10, t_grammer.c3[1:2] = c5[1:2], t_grammer.c4.a = VALUES(c1);
SET CURRENT_SCHEMA TO upsert_test;
DROP SCHEMA upsert_test_tmpschema;
-- support data type
INSERT INTO t_data VALUES(11, 11, 11, 11, 11, '11', '11', '11', '2020-04-23', '2020-04-23 11:00', '1:00') ON DUPLICATE KEY UPDATE NOTHING;
INSERT INTO t_data VALUES(12, 12, 12, 12, 12, '12', '12', '12', '2020-04-24', '2020-04-24 11:00', '2:00')
ON DUPLICATE KEY UPDATE
c_tiny = 13, c_smallint = 13, c_bigint = 13, c_numeric = 13,
c_var = '13', c_text = '13', c_bytea = '13', c_date = '2020-05-24', c_timestamp = '2020-05-24 11:00', c_time = '3:00';
INSERT INTO t_data VALUES(13, 13, 13, 13, 13, '13', '13', '13', '2020-04-25', '2020-04-25 11:00', '4:00')
ON DUPLICATE KEY UPDATE
c_tiny = EXCLUDED.c_tiny + 1, c_smallint = EXCLUDED.c_smallint + 1, c_bigint = EXCLUDED.c_bigint + 1, c_numeric = EXCLUDED.c_numeric + 1,
c_var = EXCLUDED.c_var || '3', c_text = EXCLUDED.c_text || '3', c_bytea = EXCLUDED.c_bytea || '3',
c_date = EXCLUDED.c_date + '1 day'::interval, c_timestamp = EXCLUDED.c_timestamp + '1 day'::interval, c_time = EXCLUDED.c_time + '1 hour'::interval;
-- support UPDATE to default
INSERT INTO t_default DEFAULT VALUES ON DUPLICATE KEY UPDATE c2 = 100, c3 = '2020-05-17';
INSERT INTO t_default VALUES(91, 0.91, '2020-05-17') ON DUPLICATE KEY UPDATE c2 = DEFAULT, c3 = DEFAULT;
INSERT INTO t_default VALUES(92, DEFAULT, '2020-05-17') ON DUPLICATE KEY UPDATE c2 = 10, c3 = DEFAULT;
-- unsupport alias
INSERT INTO t_grammer AS alias VALUES (91) ON DUPLICATE KEY UPDATE c2 = VALUES(c1);
ERROR: syntax error at or near "AS"
LINE 1: INSERT INTO t_grammer AS alias VALUES (91) ON DUPLICATE KEY ...
^
-- unsupport VALUES with expr
INSERT INTO t_grammer VALUES(0, 0) ON DUPLICATE KEY UPDATE c2 = sqrt(VALUES(c2));
ERROR: syntax error at or near "("
LINE 1: ... VALUES(0, 0) ON DUPLICATE KEY UPDATE c2 = sqrt(VALUES(c2));
^
INSERT INTO t_grammer VALUES(0, 0) ON DUPLICATE KEY UPDATE c2 = VALUES(c3[1]) + 1;
ERROR: syntax error at or near "+"
LINE 1: ...VALUES(0, 0) ON DUPLICATE KEY UPDATE c2 = VALUES(c3[1]) + 1;
^
INSERT INTO t_grammer VALUES(0, 0) ON DUPLICATE KEY UPDATE c2 = VALUES(c4.a) + 1;
ERROR: only allow column name within VALUES
LINE 1: ... VALUES(0, 0) ON DUPLICATE KEY UPDATE c2 = VALUES(c4.a) + 1;
^
INSERT INTO t_grammer VALUES(0, 0) ON DUPLICATE KEY UPDATE c2 = VALUES(t_grammer.c3[1]) + 1;
ERROR: only allow column name within VALUES
LINE 1: ... VALUES(0, 0) ON DUPLICATE KEY UPDATE c2 = VALUES(t_grammer....
^
-- unsupport VALUES with table name
INSERT INTO t_grammer VALUES(0, 0) ON DUPLICATE KEY UPDATE c2 = VALUES(t_grammer.c4.a);
ERROR: only allow column name within VALUES
LINE 1: ... VALUES(0, 0) ON DUPLICATE KEY UPDATE c2 = VALUES(t_grammer....
^
INSERT INTO t_grammer VALUES(0, 0) ON DUPLICATE KEY UPDATE c2 = VALUES(t_grammer.c2);
ERROR: only allow column name within VALUES
LINE 1: ... VALUES(0, 0) ON DUPLICATE KEY UPDATE c2 = VALUES(t_grammer....
^
-- unsupport DEFAULT with expr
INSERT INTO t_grammer VALUES(0, 0) ON DUPLICATE KEY UPDATE c2 = DEFAULT + 1;
ERROR: syntax error at or near "+"
LINE 1: ...ammer VALUES(0, 0) ON DUPLICATE KEY UPDATE c2 = DEFAULT + 1;
^
-- unsupport user defined typed column's element
INSERT INTO t_grammer VALUES(0, 0) ON DUPLICATE KEY UPDATE c2 = VALUES(c4.a);
ERROR: only allow column name within VALUES
LINE 1: ...mmer VALUES(0, 0) ON DUPLICATE KEY UPDATE c2 = VALUES(c4.a);
^
INSERT INTO t_grammer VALUES(0, 0) ON DUPLICATE KEY UPDATE c2 = EXCLUDED.c4.a;
ERROR: schema "excluded" does not exist
CONTEXT: referenced column: c2
INSERT INTO t_grammer VALUES(0, 0) ON DUPLICATE KEY UPDATE c2 = c4.a;
ERROR: missing FROM-clause entry for table "c4"
LINE 1: ...TO t_grammer VALUES(0, 0) ON DUPLICATE KEY UPDATE c2 = c4.a;
^
CONTEXT: referenced column: c2
SELECT * FROM t_data ORDER BY 1;
c_int | c_tiny | c_smallint | c_bigint | c_numeric | c_var | c_text | c_bytea | c_date | c_timestamp | c_time | c_intarray | c_com
-------+--------+------------+----------+-----------+-------+--------+---------+--------------------------+--------------------------+----------+------------+-------
11 | 11 | 11 | 11 | 11 | 11 | 11 | \x3131 | Thu Apr 23 00:00:00 2020 | Thu Apr 23 11:00:00 2020 | 01:00:00 | |
12 | 12 | 12 | 12 | 12 | 12 | 12 | \x3132 | Fri Apr 24 00:00:00 2020 | Fri Apr 24 11:00:00 2020 | 02:00:00 | |
13 | 13 | 13 | 13 | 13 | 13 | 13 | \x3133 | Sat Apr 25 00:00:00 2020 | Sat Apr 25 11:00:00 2020 | 04:00:00 | |
(3 rows)
SELECT * FROM t_grammer ORDER BY 1;
c1 | c2 | c3 | c4 | c5
-----+------+---------------+-----------+-----------
11 | 1 | | |
12 | 2 | | |
23 | -100 | | |
24 | -100 | | |
31 | 1 | | |
32 | 2 | | |
41 | 1 | | |
42 | 2 | | |
51 | 1 | | |
52 | 2 | | |
53 | 3 | | |
54 | 4 | | |
55 | 5 | | |
61 | 1 | | |
62 | 2 | | |
63 | 3 | | |
64 | 4 | {10,20,30} | |
65 | 5 | {10,20,30} | |
66 | 6 | {10,20,30} | |
67 | 7 | {10,20,30} | |
68 | 8 | {10,20,30} | |
69 | 9 | {10,20,30} | |
71 | 1 | | |
72 | 2 | {71,72,73} | |
73 | 3 | {71,72,73} | |
74 | 4 | {71,72,73} | (74,75) |
81 | -100 | | | {81,82}
82 | -100 | {881,882} | |
83 | -100 | {81,82,83} | (810,820) |
84 | -100 | {81,82,83} | (850,) |
91 | 1 | {91,92,93} | (94,95) |
92 | -100 | | (910,920) | {91,92}
101 | 1 | {102,103,104} | (105,106) | {107,108}
102 | 2 | {102,103,104} | (105,106) | {107,108}
103 | 3 | {102,103,104} | (105,106) | {107,108}
(35 rows)
SELECT * FROM t_default ORDER BY 1;
--? c1 | c2 | c3
--?
--? 10 | .396464773453772 | Wed Apr 29 10:25:23.202729 2020
--? 91 | .91 | Sun May 17 00:00:00 2020
--? 92 | .840485369320959 | Sun May 17 00:00:00 2020
(3 rows)

View File

@ -0,0 +1,188 @@
\c upsert
SET CURRENT_SCHEMA TO upsert_test;
-- enable_upsert_to_merge must be off, or upsert will be translated to merge.
SET enable_upsert_to_merge TO OFF;
SHOW enable_upsert_to_merge;
enable_upsert_to_merge
------------------------
off
(1 row)
-- support multiple set
INSERT INTO t_grammer VALUES(11, 1) ON DUPLICATE KEY UPDATE c2 = 2, c4 = ROW(10, 20), c3 = '{10, 20, 30}';
INSERT INTO t_grammer VALUES(12, 2) ON DUPLICATE KEY UPDATE c2 = 2, c3[1] = 3;
-- support const value and expr
INSERT INTO t_grammer VALUES(23) ON DUPLICATE KEY UPDATE c2 = 2;
INSERT INTO t_grammer VALUES(24) ON DUPLICATE KEY UPDATE c2 = length('test') + 100;
-- support without table name
INSERT INTO t_grammer VALUES(31, 1) ON DUPLICATE KEY UPDATE c2 = c1, c4.a = VALUES(c1);
INSERT INTO t_grammer VALUES(32, 2) ON DUPLICATE KEY UPDATE c2 = c1 + 5, c4.a = VALUES(c1);
-- support with table name
INSERT INTO t_grammer VALUES(41, 1) ON DUPLICATE KEY UPDATE c2 = t_grammer.c1, c4.a = VALUES(c1);
INSERT INTO t_grammer VALUES(42, 2) ON DUPLICATE KEY UPDATE c2 = t_grammer.c1 + 5, c4.a = VALUES(c1);
-- support EXCLUDED alone and with expr
INSERT INTO t_grammer VALUES(51, 1) ON DUPLICATE KEY UPDATE c2 = c1 + 5, c4.a = EXCLUDED.c1;
INSERT INTO t_grammer VALUES(52, 2) ON DUPLICATE KEY UPDATE c2 = t_grammer.c1 + 5, c4.a = EXCLUDED.c1 + 5;
INSERT INTO t_grammer VALUES(53, 3) ON DUPLICATE KEY UPDATE c4.a = sqrt(EXCLUDED.c1 - EXCLUDED.c2 - 1) + 1, c2 = t_grammer.c1 + 5;
INSERT INTO t_grammer VALUES(54, 4) ON DUPLICATE KEY UPDATE c4.b = EXCLUDED.c1 + t_grammer.c1;
INSERT INTO t_grammer VALUES(55, 5) ON DUPLICATE KEY UPDATE c4.a = EXCLUDED.c2, c4.b = EXCLUDED.c1 + sqrt(c1 - 6);
-- support ARRAY
INSERT INTO t_grammer VALUES(61, 1) ON DUPLICATE KEY UPDATE c2 = VALUES(c3[1]);
INSERT INTO t_grammer VALUES(62, 2) ON DUPLICATE KEY UPDATE c5 = VALUES(c3[2,3]);
INSERT INTO t_grammer VALUES(63, 3) ON DUPLICATE KEY UPDATE c5 = VALUES(c3[2:3]);
INSERT INTO t_grammer VALUES(64, 4, '{10, 20, 30}') ON DUPLICATE KEY UPDATE c2 = EXCLUDED.c3[1];
INSERT INTO t_grammer VALUES(65, 5, '{10, 20, 30}') ON DUPLICATE KEY UPDATE c5 = EXCLUDED.c3[2,3];
INSERT INTO t_grammer VALUES(66, 6, '{10, 20, 30}') ON DUPLICATE KEY UPDATE c5 = EXCLUDED.c3[1:2];
INSERT INTO t_grammer VALUES(67, 7, '{10, 20, 30}') ON DUPLICATE KEY UPDATE c2 = c3[1];
INSERT INTO t_grammer VALUES(68, 8, '{10, 20, 30}') ON DUPLICATE KEY UPDATE c5 = c3[2,3];
INSERT INTO t_grammer VALUES(69, 9, '{10, 20, 30}') ON DUPLICATE KEY UPDATE c5 = c3[1:2];
-- support user defined type
INSERT INTO t_grammer VALUES(71, 1) ON DUPLICATE KEY UPDATE c4.a = c3[1] + c1;
INSERT INTO t_grammer VALUES(72, 2, '{71, 72, 73}') ON DUPLICATE KEY UPDATE c4.a = c3[1] + c1;
INSERT INTO t_grammer VALUES(73, 3, '{71, 72, 73}') ON DUPLICATE KEY UPDATE c4.a = c3[1] + c1, c4.b = c3[2];
INSERT INTO t_grammer VALUES(74, 4, '{71, 72, 73}', ROW(74, 75)) ON DUPLICATE KEY UPDATE c4 = ROW(740, 750);
-- appoint INSERT target column
INSERT INTO t_grammer (c5, c1, c2) VALUES('{81,82}', 81, DEFAULT) ON DUPLICATE KEY UPDATE c2 = VALUES(c1);
INSERT INTO t_grammer (c3[1], c3[2], c1) VALUES(881, 882, 82) ON DUPLICATE KEY UPDATE c5 = VALUES(c3), c2 = VALUES(c3[1]);
INSERT INTO t_grammer (c1, c3, c4) VALUES(83, '{81, 82, 83}', ROW(810, 820)) ON DUPLICATE KEY UPDATE c4 = EXCLUDED.c4;
INSERT INTO t_grammer (c1, c3, c4.a) VALUES(84, '{81, 82, 83}', 850) ON DUPLICATE KEY UPDATE c4.b = c3[3];
-- support UPDATE NOTHING
INSERT INTO t_grammer VALUES(91, 1, '{91, 92, 93}', ROW(94, 95)) ON DUPLICATE KEY UPDATE NOTHING;
INSERT INTO t_grammer (c5, c1, c2, c4) VALUES('{91,92}', 92, DEFAULT, ROW(910, 920)) ON DUPLICATE KEY UPDATE NOTHING;
-- UPDATE target: unsupport with schema but support with tablename
INSERT INTO t_grammer VALUES(0, 0, '{0,0}', ROW(0, 0), '{107, 108}') ON DUPLICATE KEY UPDATE
upsert_test.t_grammer.c2 = c2 * 10, upsert_test.t_grammer.c3[1:2] = c5[1:2], upsert_test.t_grammer.c4.a = c1;
ERROR: column "upsert_test.t_grammer" of relation "t_grammer" does not exist
LINE 2: upsert_test.t_grammer.c2 = c2 * 10, upsert_test.t_grammer.c...
^
INSERT INTO t_grammer VALUES(101, 1, '{102, 103, 104}', ROW(105, 106), '{107, 108}') ON DUPLICATE KEY UPDATE
t_grammer.c2 = c2 * 10, t_grammer.c3[1:2] = c5[1:2], t_grammer.c4.a = c1;
-- INSERT target: appoint schema
INSERT INTO upsert_test.t_grammer VALUES(102, 2, '{102, 103, 104}', ROW(105, 106), '{107, 108}') ON DUPLICATE KEY UPDATE
t_grammer.c2 = EXCLUDED.c2 * 10, t_grammer.c3[1:2] = c5[1:2], t_grammer.c4.a = VALUES(c1);
CREATE SCHEMA upsert_test_tmp;
SET CURRENT_SCHEMA TO upsert_test_tmp;
INSERT INTO upsert_test.t_grammer VALUES(103, 3, '{102, 103, 104}', ROW(105, 106), '{107, 108}') ON DUPLICATE KEY UPDATE
t_grammer.c2 = EXCLUDED.c2 * 10, t_grammer.c3[1:2] = c5[1:2], t_grammer.c4.a = VALUES(c1);
SET CURRENT_SCHEMA TO upsert_test;
DROP SCHEMA upsert_test_tmp;
-- support data type
INSERT INTO t_data VALUES(11, 11, 11, 11, 11, '11', '11', '11', '2020-04-23', '2020-04-23 11:00', '1:00') ON DUPLICATE KEY UPDATE NOTHING;
INSERT INTO t_data VALUES(12, 12, 12, 12, 12, '12', '12', '12', '2020-04-24', '2020-04-24 11:00', '2:00')
ON DUPLICATE KEY UPDATE
c_tiny = 13, c_smallint = 13, c_bigint = 13, c_numeric = 13,
c_var = '13', c_text = '13', c_bytea = '13', c_date = '2020-05-24', c_timestamp = '2020-05-24 11:00', c_time = '3:00';
INSERT INTO t_data VALUES(13, 13, 13, 13, 13, '13', '13', '13', '2020-04-25', '2020-04-25 11:00', '4:00')
ON DUPLICATE KEY UPDATE
c_tiny = EXCLUDED.c_tiny + 1, c_smallint = EXCLUDED.c_smallint + 1, c_bigint = EXCLUDED.c_bigint + 1, c_numeric = EXCLUDED.c_numeric + 1,
c_var = EXCLUDED.c_var || '3', c_text = EXCLUDED.c_text || '3', c_bytea = EXCLUDED.c_bytea || '3',
c_date = EXCLUDED.c_date + '1 day'::interval, c_timestamp = EXCLUDED.c_timestamp + '1 day'::interval, c_time = EXCLUDED.c_time + '1 hour'::interval;
-- support UPDATE to default
INSERT INTO t_default DEFAULT VALUES ON DUPLICATE KEY UPDATE c2 = 100, c3 = '2020-05-17';
INSERT INTO t_default VALUES(91, 0.91, '2020-05-17') ON DUPLICATE KEY UPDATE c2 = DEFAULT, c3 = DEFAULT;
INSERT INTO t_default VALUES(92, DEFAULT, '2020-05-17') ON DUPLICATE KEY UPDATE c2 = 10, c3 = DEFAULT;
-- unsupport alias
INSERT INTO t_grammer AS alias VALUES (91) ON DUPLICATE KEY UPDATE c2 = VALUES(c1);
ERROR: syntax error at or near "AS"
LINE 1: INSERT INTO t_grammer AS alias VALUES (91) ON DUPLICATE KEY ...
^
-- unsupport VALUES with expr
INSERT INTO t_grammer VALUES(0, 0) ON DUPLICATE KEY UPDATE c2 = sqrt(VALUES(c2));
ERROR: syntax error at or near "("
LINE 1: ... VALUES(0, 0) ON DUPLICATE KEY UPDATE c2 = sqrt(VALUES(c2));
^
INSERT INTO t_grammer VALUES(0, 0) ON DUPLICATE KEY UPDATE c2 = VALUES(c3[1]) + 1;
ERROR: syntax error at or near "+"
LINE 1: ...VALUES(0, 0) ON DUPLICATE KEY UPDATE c2 = VALUES(c3[1]) + 1;
^
INSERT INTO t_grammer VALUES(0, 0) ON DUPLICATE KEY UPDATE c2 = VALUES(c4.a) + 1;
ERROR: only allow column name within VALUES
LINE 1: ... VALUES(0, 0) ON DUPLICATE KEY UPDATE c2 = VALUES(c4.a) + 1;
^
INSERT INTO t_grammer VALUES(0, 0) ON DUPLICATE KEY UPDATE c2 = VALUES(t_grammer.c3[1]) + 1;
ERROR: only allow column name within VALUES
LINE 1: ... VALUES(0, 0) ON DUPLICATE KEY UPDATE c2 = VALUES(t_grammer....
^
-- unsupport VALUES with table name
INSERT INTO t_grammer VALUES(0, 0) ON DUPLICATE KEY UPDATE c2 = VALUES(t_grammer.c4.a);
ERROR: only allow column name within VALUES
LINE 1: ... VALUES(0, 0) ON DUPLICATE KEY UPDATE c2 = VALUES(t_grammer....
^
INSERT INTO t_grammer VALUES(0, 0) ON DUPLICATE KEY UPDATE c2 = VALUES(t_grammer.c2);
ERROR: only allow column name within VALUES
LINE 1: ... VALUES(0, 0) ON DUPLICATE KEY UPDATE c2 = VALUES(t_grammer....
^
-- unsupport DEFAULT with expr
INSERT INTO t_grammer VALUES(0, 0) ON DUPLICATE KEY UPDATE c2 = DEFAULT + 1;
ERROR: syntax error at or near "+"
LINE 1: ...ammer VALUES(0, 0) ON DUPLICATE KEY UPDATE c2 = DEFAULT + 1;
^
-- unsupport user defined typed column's element
INSERT INTO t_grammer VALUES(0, 0) ON DUPLICATE KEY UPDATE c2 = VALUES(c4.a);
ERROR: only allow column name within VALUES
LINE 1: ...mmer VALUES(0, 0) ON DUPLICATE KEY UPDATE c2 = VALUES(c4.a);
^
INSERT INTO t_grammer VALUES(0, 0) ON DUPLICATE KEY UPDATE c2 = EXCLUDED.c4.a;
ERROR: schema "excluded" does not exist
CONTEXT: referenced column: c2
INSERT INTO t_grammer VALUES(0, 0) ON DUPLICATE KEY UPDATE c2 = c4.a;
ERROR: missing FROM-clause entry for table "c4"
LINE 1: ...TO t_grammer VALUES(0, 0) ON DUPLICATE KEY UPDATE c2 = c4.a;
^
CONTEXT: referenced column: c2
SELECT * FROM t_data ORDER BY 1;
c_int | c_tiny | c_smallint | c_bigint | c_numeric | c_var | c_text | c_bytea | c_date | c_timestamp | c_time | c_intarray | c_com
-------+--------+------------+----------+-----------+-------+--------+----------+--------------------------+--------------------------+----------+------------+-------
11 | 11 | 11 | 11 | 11 | 11 | 11 | \x3131 | Thu Apr 23 00:00:00 2020 | Thu Apr 23 11:00:00 2020 | 01:00:00 | |
12 | 13 | 13 | 13 | 13 | 13 | 13 | \x3133 | Sun May 24 00:00:00 2020 | Sun May 24 11:00:00 2020 | 03:00:00 | |
13 | 14 | 14 | 14 | 14 | 133 | 133 | \x313333 | Sun Apr 26 00:00:00 2020 | Sun Apr 26 11:00:00 2020 | 05:00:00 | |
(3 rows)
SELECT * FROM t_grammer ORDER BY 1;
c1 | c2 | c3 | c4 | c5
-----+------+---------------+-----------+-----------
11 | 2 | {10,20,30} | (10,20) |
12 | 2 | {3} | |
23 | 2 | | |
24 | 104 | | |
31 | 31 | | (31,) |
32 | 37 | | (32,) |
41 | 41 | | (41,) |
42 | 47 | | (42,) |
51 | 56 | | (51,) |
52 | 57 | | (57,) |
53 | 58 | | (8,) |
54 | 4 | | (,108) |
55 | 5 | | (5,62) |
61 | | | |
62 | 2 | | |
63 | 3 | | |
64 | 10 | {10,20,30} | |
65 | 5 | {10,20,30} | | {20,30}
66 | 6 | {10,20,30} | | {10,20}
67 | 10 | {10,20,30} | |
68 | 8 | {10,20,30} | | {20,30}
69 | 9 | {10,20,30} | | {10,20}
71 | 1 | | (,) |
72 | 2 | {71,72,73} | (143,) |
73 | 3 | {71,72,73} | (144,72) |
74 | 4 | {71,72,73} | (740,750) |
81 | 81 | | | {81,82}
82 | 881 | {881,882} | | {881,882}
83 | -100 | {81,82,83} | (810,820) |
84 | -100 | {81,82,83} | (850,83) |
91 | 1 | {91,92,93} | (94,95) |
92 | -100 | | (910,920) | {91,92}
101 | 10 | {107,108,104} | (101,106) | {107,108}
102 | 20 | {107,108,104} | (102,106) | {107,108}
103 | 30 | {107,108,104} | (103,106) | {107,108}
(35 rows)
SELECT * FROM t_default ORDER BY 1;
--? c1 | c2 | c3
--?
--? 10 | 100 | Sun May 17 00:00:00 2020
--? 91 | .840485369320959 | Wed Apr 29 10:25:28.439693 2020
--? 92 | 10 | Wed Apr 29 10:25:28.442916 2020
(3 rows)

View File

@ -0,0 +1,92 @@
-- Note: about upsert test
-- test point:
-- grammer
-- table, unlogged table, temp table, matview
-- constraint(primary key, index, foreign key, null ...)
-- trigger
-- sequence
CREATE DATABASE upsert WITH TEMPLATE template0 ENCODING 'UTF8';
\c upsert
-- grammer test
CREATE SCHEMA upsert_test;
SET CURRENT_SCHEMA TO upsert_test;
CREATE TYPE atype AS(a int, b int);
CREATE TYPE btype AS(a int, b atype, c varchar[3]);
CREATE TABLE t_grammer (c1 INT PRIMARY KEY, c2 INT DEFAULT -100, c3 int[3], c4 atype, c5 int[2]);
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "t_grammer_pkey" for table "t_grammer"
CREATE TABLE t_default (c1 INT PRIMARY KEY DEFAULT 10, c2 FLOAT DEFAULT random(), c3 TIMESTAMP DEFAULT current_timestamp);
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "t_default_pkey" for table "t_default"
CREATE TABLE t_data (c_int INT PRIMARY KEY, c_tiny TINYINT, c_smallint SMALLINT, c_bigint BIGINT, c_numeric NUMERIC,
c_var VARCHAR, c_text TEXT, c_bytea BYTEA, c_date DATE, c_timestamp TIMESTAMP, c_time TIME,
c_intarray INT[3], c_com atype);
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "t_data_pkey" for table "t_data"
CREATE TABLE t_trigger (key INT PRIMARY KEY, color TEXT);
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "t_trigger_pkey" for table "t_trigger"
-- unlogged table
CREATE SCHEMA upsert_test_unlog;
SET CURRENT_SCHEMA TO upsert_test_unlog;
CREATE TYPE atype AS(a int, b int);
CREATE TYPE btype AS(a int, b atype, c varchar[3]);
CREATE UNLOGGED TABLE t_hash_unlog_0 (c1 INT, c2 INT, c3 VARCHAR, c4 INT[3], c5 INT[5], c6 atype, c7 btype);
CREATE UNLOGGED TABLE t_hash_unlog_1 (c1 INT, c2 INT PRIMARY KEY, c3 VARCHAR, c4 INT[3], c5 INT[5], c6 atype, c7 btype);
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "t_hash_unlog_1_pkey" for table "t_hash_unlog_1"
CREATE UNLOGGED TABLE t_rep_unlog_0 (c1 INT, c2 INT, c3 VARCHAR, c4 INT[3], c5 INT[5], c6 atype, c7 btype) ;
CREATE UNLOGGED TABLE t_rep_unlog_1 (c1 INT, c2 INT PRIMARY KEY, c3 VARCHAR, c4 INT[3], c5 INT[5], c6 atype, c7 btype);
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "t_rep_unlog_1_pkey" for table "t_rep_unlog_1"
-- temp table
-- temp table can not be created here, we create it in upsert_tmp_test.
-- restriction test
CREATE SCHEMA upsert_test_etc;
SET CURRENT_SCHEMA TO upsert_test_etc;
create table up_neg_01 (c1 int, c2 int, c3 int) with (ORIENTATION = COLUMN);
create table up_neg_02 (c1 int, c2 int, c3 int) with (ORIENTATION = COLUMN);
create table up_neg_03 (c1 int, c2 int UNIQUE DEFERRABLE, c3 int);
NOTICE: CREATE TABLE / UNIQUE will create implicit index "up_neg_03_c2_key" for table "up_neg_03"
create table up_neg_04 (c1 int, c2 int UNIQUE, c3 int);
NOTICE: CREATE TABLE / UNIQUE will create implicit index "up_neg_04_c2_key" for table "up_neg_04"
create table up_neg_05(c1 int, c2 int, c3 int, c4 int unique, c5 int primary key, unique(c2,c3));
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "up_neg_05_pkey" for table "up_neg_05"
NOTICE: CREATE TABLE / UNIQUE will create implicit index "up_neg_05_c4_key" for table "up_neg_05"
NOTICE: CREATE TABLE / UNIQUE will create implicit index "up_neg_05_c2_c3_key" for table "up_neg_05"
create table up_neg_0(c1 int, c2 int, c3 int, c4 int unique, c5 int primary key, unique(c2,c3)) ;
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "up_neg_0_pkey" for table "up_neg_0"
NOTICE: CREATE TABLE / UNIQUE will create implicit index "up_neg_0_c4_key" for table "up_neg_0"
NOTICE: CREATE TABLE / UNIQUE will create implicit index "up_neg_0_c2_c3_key" for table "up_neg_0"
create table up_neg_06(c1 int, c2 int, c3 int unique) ;
NOTICE: CREATE TABLE / UNIQUE will create implicit index "up_neg_06_c3_key" for table "up_neg_06"
create table up_neg_07(c1 int, c2 int, c3 int unique) ;
NOTICE: CREATE TABLE / UNIQUE will create implicit index "up_neg_07_c3_key" for table "up_neg_07"
create table up_neg_08(c1 int, c2 int, c3 int unique) ;
NOTICE: CREATE TABLE / UNIQUE will create implicit index "up_neg_08_c3_key" for table "up_neg_08"
create table up_neg_09(c1 int, c2 int, c3 int, unique(c2,c3)) ;
NOTICE: CREATE TABLE / UNIQUE will create implicit index "up_neg_09_c2_c3_key" for table "up_neg_09"
create table up_neg_10(c1 int, c2 int, c3 int, unique(c2,c3)) ;
NOTICE: CREATE TABLE / UNIQUE will create implicit index "up_neg_10_c2_c3_key" for table "up_neg_10"
create view up_view as select *from up_neg_01;
create materialized view mat_view as select *from up_neg_01;
create table pkt (a int primary key, b int, c int);
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "pkt_pkey" for table "pkt"
create table fkt (a int primary key, b int references pkt, c int);
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "fkt_pkey" for table "fkt"
-- procedure test
CREATE SCHEMA upsert_test_procedure;
-- explain test
CREATE SCHEMA upsert_test_explain;
SET CURRENT_SCHEMA TO upsert_test_explain;
create table up_expl_hash(c1 int, c2 int, c3 int unique) ;
NOTICE: CREATE TABLE / UNIQUE will create implicit index "up_expl_hash_c3_key" for table "up_expl_hash"
create table up_expl_repl(c1 int, c2 int, c3 int unique) ;
NOTICE: CREATE TABLE / UNIQUE will create implicit index "up_expl_repl_c3_key" for table "up_expl_repl"
create table up_expl_part(c1 int, c2 int, c3 int unique) ;
NOTICE: CREATE TABLE / UNIQUE will create implicit index "up_expl_part_c3_key" for table "up_expl_part"
create unlogged table up_expl_unlog(c1 int, c2 int, c3 int unique) ;
NOTICE: CREATE TABLE / UNIQUE will create implicit index "up_expl_unlog_c3_key" for table "up_expl_unlog"
create table up_expl_node(c1 int, c2 int, c3 int unique) ;
NOTICE: CREATE TABLE / UNIQUE will create implicit index "up_expl_node_c3_key" for table "up_expl_node"
create table up_expl_repl(c1 int, c2 int, c3 int unique) ;
ERROR: relation "up_expl_repl" already exists
create table up_expl_repl2(c1 int, c2 int, c3 int, c4 int unique, c5 int primary key, unique(c2,c3));
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "up_expl_repl2_pkey" for table "up_expl_repl2"
NOTICE: CREATE TABLE / UNIQUE will create implicit index "up_expl_repl2_c4_key" for table "up_expl_repl2"
NOTICE: CREATE TABLE / UNIQUE will create implicit index "up_expl_repl2_c2_c3_key" for table "up_expl_repl2"
-- create temp table up_expl_temp(c1 int, c2 int, c3 int unique);

View File

@ -0,0 +1,4 @@
CREATE DATABASE upsert_etc;
\c upsert_etc;
CREATE SCHEMA upsert_test_etc;
SET CURRENT_SCHEMA TO upsert_test_etc;

View File

@ -0,0 +1,229 @@
/*
* upsert negative test cases
*
table cases
col table
ORC table
VIEW
MAT view
index
DEFERABLE index
insert stmt
returning
with
with recur
update stmt
VALUES with expr
update distribute key
update primary key
update unique key
update partition key
where clause
with clause
sub query
*/
--------------------------------------------------------------------------------------------
\c upsert
SET CURRENT_SCHEMA TO upsert_test_etc;
-- enable_upsert_to_merge must be off, or upsert will be translated to merge.
SET enable_upsert_to_merge TO OFF;
SHOW enable_upsert_to_merge;
enable_upsert_to_merge
------------------------
off
(1 row)
insert into up_neg_04 select a,a,a from generate_series(1,20) as a;
insert into up_neg_05 select a,a,a,a,a from generate_series(1,20) as a;
insert into up_neg_06 select a,a,a from generate_series(1,20) as a;
insert into up_neg_07 select a,a,a from generate_series(1,20) as a;
insert into up_neg_08 select a,a,a from generate_series(1,20) as a;
insert into up_neg_09 select a,a,a from generate_series(1,20) as a;
insert into up_neg_10 select a,a,a from generate_series(1,20) as a;
-- table cases
---- col table
insert into up_neg_01 values(1,2,3) on duplicate key update c3 = 1;
ERROR: INSERT ON DUPLICATE KEY UPDATE is not supported on column orientated table.
---- ORC table
insert into up_neg_02 values(1,2,3) on duplicate key update c3 = 1;
ERROR: INSERT ON DUPLICATE KEY UPDATE is not supported on column orientated table.
---- VIEW
insert into up_view values(1) on duplicate key update c3 = 1;
ERROR: INSERT ON DUPLICATE KEY UPDATE is not supported on VIEW.
-- matview
refresh materialized view mat_view;
insert into mat_view values(1) on duplicate key update c3 = 1;
ERROR: cannot change materialized view "mat_view"
-- index
---- DEFERABLE index
insert into up_neg_03 values(1,2,3) on duplicate key update c1 = 1;
ERROR: INSERT ON DUPLICATE KEY UPDATE does not support deferrable unique constraints/exclusion constraints.
insert into up_neg_03 values(1) on duplicate key update c1 = 1;
ERROR: INSERT ON DUPLICATE KEY UPDATE does not support deferrable unique constraints/exclusion constraints.
-- insert stmt
----returning
insert into up_neg_04 values(1,1,1) on duplicate key update c1 = 1 returning c1;
ERROR: RETURNING clause is not yet supported whithin INSERT ON DUPLICATE KEY UPDATE statement.
----with
with sub as (select *from up_neg_04)
insert into up_neg_04 select *from sub on duplicate key update c1 =1;
ERROR: WITH clause is not yet supported whithin INSERT ON DUPLICATE KEY UPDATE statement.
----with recur
with RECURSIVE sub as (select *from up_neg_04)
insert into up_neg_04 select *from sub on duplicate key update c1 =1;
ERROR: WITH clause is not yet supported whithin INSERT ON DUPLICATE KEY UPDATE statement.
with sub as (select *from up_neg_04)
insert into up_neg_04 select *from sub on duplicate key update c1 =1 returning c1;
ERROR: RETURNING clause is not yet supported whithin INSERT ON DUPLICATE KEY UPDATE statement.
-- update stmt
---- VALUES with expr
insert into up_neg_05 values(1,1,1,1) on duplicate key update c3 = values(1+100);
ERROR: syntax error at or near "1"
LINE 1: ... values(1,1,1,1) on duplicate key update c3 = values(1+100);
^
insert into up_neg_05 values(1,1,1,1) on duplicate key update c3 = values(100);
ERROR: syntax error at or near "100"
LINE 1: ...05 values(1,1,1,1) on duplicate key update c3 = values(100);
^
insert into up_neg_05 values(1,1,1,1,1) on duplicate key update c1 = 1;
---- update primary key
insert into up_neg_05 values(1,1,1,1,1) on duplicate key update c5 = 1;
ERROR: INSERT ON DUPLICATE KEY UPDATE don't allow update on primary key or unique key.
---- update unique key
insert into up_neg_05 values(1,1,1,1,1) on duplicate key update c4 = 1;
ERROR: INSERT ON DUPLICATE KEY UPDATE don't allow update on primary key or unique key.
insert into up_neg_05 values(1,1,1,1,1) on duplicate key update c2 = 1, c3=2;
ERROR: INSERT ON DUPLICATE KEY UPDATE don't allow update on primary key or unique key.
insert into up_neg_05 values(1,1,1,1,1) on duplicate key update c2 = 1;
ERROR: INSERT ON DUPLICATE KEY UPDATE don't allow update on primary key or unique key.
insert into up_neg_05 values(1,1,1,1,1) on duplicate key update c3 = 2;
ERROR: INSERT ON DUPLICATE KEY UPDATE don't allow update on primary key or unique key.
insert into up_neg_05 values(1,1,1,1,1) on duplicate key update c1 =1, c2 = 1, c3=2, c4=1,c5=1;
ERROR: INSERT ON DUPLICATE KEY UPDATE don't allow update on primary key or unique key.
---- where clause
insert into up_neg_05 values(1,1,1,1,1) on duplicate key update c4 = 1 where c1=1;
ERROR: syntax error at or near "where"
LINE 1: ... values(1,1,1,1,1) on duplicate key update c4 = 1 where c1=1...
^
---- from clause
insert into up_neg_05 values(1,1,1,1,1) on duplicate key update c4 = 1 from up_neg_04 where c1=1;
ERROR: syntax error at or near "from"
LINE 1: ... values(1,1,1,1,1) on duplicate key update c4 = 1 from up_ne...
^
---- sub query
insert into up_neg_05 values(1,1,1,1,1) on duplicate key update (c2) = (select c2 from up_neg_05);
ERROR: Update with subquery is not yet supported whithin INSERT ON DUPLICATE KEY UPDATE statement.
---- update distribute key
insert into up_neg_06 values(101, 1, 1) on duplicate key update c3=101;
ERROR: INSERT ON DUPLICATE KEY UPDATE don't allow update on primary key or unique key.
---- update partition key
insert into up_neg_07 values(101, 1, 300) on duplicate key update c3=101;
ERROR: INSERT ON DUPLICATE KEY UPDATE don't allow update on primary key or unique key.
insert into up_neg_08 values(101, 1, 300) on duplicate key update c3=101;
ERROR: INSERT ON DUPLICATE KEY UPDATE don't allow update on primary key or unique key.
insert into up_neg_09 values(101, 1, 1) on duplicate key update c3=101;
ERROR: INSERT ON DUPLICATE KEY UPDATE don't allow update on primary key or unique key.
insert into up_neg_09 values(101, 1, 1) on duplicate key update c2=101;
ERROR: INSERT ON DUPLICATE KEY UPDATE don't allow update on primary key or unique key.
insert into up_neg_09 values(101, 1, 1) on duplicate key update c2 =1,c3=101;
ERROR: INSERT ON DUPLICATE KEY UPDATE don't allow update on primary key or unique key.
--update unique key mul type plans
EXPLAIN (VERBOSE on, COSTS off) insert into up_neg_10 values(101, 1, 300) on duplicate key update c1=101;
QUERY PLAN
-------------------------------------------------
Insert on upsert_test_etc.up_neg_10
Conflict Resolution: UPDATE
Conflict Arbiter Indexes: up_neg_10_c2_c3_key
-> Result
Output: 101, 1, 300
(5 rows)
insert into up_neg_10 values(101, 1, 300) on duplicate key update c3=101;
ERROR: INSERT ON DUPLICATE KEY UPDATE don't allow update on primary key or unique key.
--trigger
create table upsert_base
(c1 int primary key,
c2 varchar(100), --record the type
cold varchar(1024),
cnew varchar(1024) );
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "upsert_base_pkey" for table "upsert_base"
create table upsert_tri
(c1 int,
c2 varchar(100),
c3 int,
unique(c1,c3)
);
NOTICE: CREATE TABLE / UNIQUE will create implicit index "upsert_tri_c1_c3_key" for table "upsert_tri"
--S1 after trigger
CREATE OR REPLACE FUNCTION trig_after() RETURNS TRIGGER AS $emp_audit$
BEGIN
IF (TG_OP = 'INSERT') THEN
insert into upsert_base(c2,cnew) values('after insert',new.c2);
RETURN NEW;
ELSIF (TG_OP = 'UPDATE') THEN
insert into upsert_base(c2,cold,cnew) values('after update',old.c2,new.c2);
RETURN NEW;
END IF;
RETURN NULL;
END;
$emp_audit$ LANGUAGE plpgsql;
CREATE TRIGGER tri_after
AFTER UPDATE OR INSERT ON upsert_tri
FOR EACH ROW EXECUTE PROCEDURE trig_after();
--S2 before trigger
CREATE OR REPLACE FUNCTION trig_before() RETURNS TRIGGER AS $emp_audit$
BEGIN
IF (TG_OP = 'INSERT') THEN
insert into upsert_base(c2,cnew) values('before insert',new.c2);
RETURN NEW;
ELSIF (TG_OP = 'UPDATE') THEN
insert into upsert_base(c2,cold,cnew) values('before update',old.c2,new.c2);
RETURN NEW;
END IF;
RETURN NULL;
END;
$emp_audit$ LANGUAGE plpgsql;
CREATE TRIGGER tri_before
BEFORE UPDATE OR INSERT ON upsert_tri
FOR EACH ROW EXECUTE PROCEDURE trig_before();
---- upsert-insert
insert into upsert_tri(c1,c2,c3) values(1000,'abc',1) on duplicate key update nothing;
ERROR: null value in column "c1" violates not-null constraint
DETAIL: Failing row contains (null, before insert, null, abc).
CONTEXT: SQL statement "insert into upsert_base(c2,cnew) values('before insert',new.c2)"
PL/pgSQL function trig_before() line 4 at SQL statement
insert into upsert_tri(c1,c2,c3) values(2000,'abc',1) on duplicate key update c2='bcd';
ERROR: null value in column "c1" violates not-null constraint
DETAIL: Failing row contains (null, before insert, null, abc).
CONTEXT: SQL statement "insert into upsert_base(c2,cnew) values('before insert',new.c2)"
PL/pgSQL function trig_before() line 4 at SQL statement
---- upsert-nothing
insert into upsert_tri(c1,c2,c3) values(1000,'abc',1) on duplicate key update nothing;
ERROR: null value in column "c1" violates not-null constraint
DETAIL: Failing row contains (null, before insert, null, abc).
CONTEXT: SQL statement "insert into upsert_base(c2,cnew) values('before insert',new.c2)"
PL/pgSQL function trig_before() line 4 at SQL statement
---- upsert-update
insert into upsert_tri(c1,c2,c3) values(2000,'abc',1) on duplicate key update c2='bcd';
ERROR: null value in column "c1" violates not-null constraint
DETAIL: Failing row contains (null, before insert, null, abc).
CONTEXT: SQL statement "insert into upsert_base(c2,cnew) values('before insert',new.c2)"
PL/pgSQL function trig_before() line 4 at SQL statement
---- check results
SELECT * from upsert_tri;
c1 | c2 | c3
----+----+----
(0 rows)
SELECT * from upsert_base;
c1 | c2 | cold | cnew
----+----+------+------
(0 rows)
-- foreign key
insert into pkt values(1,1,1),(2,2,2),(3,3,3),(4,4,4),(5,5,5);
insert into fkt values(1,1,1),(2,2,2),(3,3,3);
insert into fkt values(1,1,1),(2,2,2),(3,3,3) on duplicate key update b=excluded.b+1, c=0;
insert into fkt values(1,1,1),(2,2,2),(3,3,3) on duplicate key update b=excluded.b+3, c=-1;
ERROR: insert or update on table "fkt" violates foreign key constraint "fkt_b_fkey"
DETAIL: Key (b)=(6) is not present in table "pkt".

View File

@ -0,0 +1,173 @@
\c upsert
CREATE SCHEMA upsert_test_tmp;
SET CURRENT_SCHEMA TO upsert_test_tmp;
CREATE TYPE atype AS(a int, b int);
CREATE TYPE btype AS(a int, b atype, c varchar[3]);
CREATE TEMP TABLE t_hash_tmp_0 (c1 INT, c2 INT, c3 VARCHAR, c4 INT[3], c5 INT[5], c6 atype, c7 btype);
CREATE TEMP TABLE t_hash_tmp_1 (c1 INT, c2 INT PRIMARY KEY, c3 VARCHAR, c4 INT[3], c5 INT[5], c6 atype, c7 btype);
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "t_hash_tmp_1_pkey" for table "t_hash_tmp_1"
CREATE TEMP TABLE t_rep_tmp_0 (c1 INT, c2 INT, c3 VARCHAR, c4 INT[3], c5 INT[5], c6 atype, c7 btype) ;
CREATE TEMP TABLE t_rep_tmp_1 (c1 INT, c2 INT PRIMARY KEY, c3 VARCHAR, c4 INT[3], c5 INT[5], c6 atype, c7 btype) ;
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "t_rep_tmp_1_pkey" for table "t_rep_tmp_1"
-- enable_upsert_to_merge must be off, or upsert will be translated to merge.
SET enable_upsert_to_merge TO OFF;
SHOW enable_upsert_to_merge;
enable_upsert_to_merge
------------------------
off
(1 row)
-- hash table
-- tmp table without primary key
INSERT INTO t_hash_tmp_0 VALUES(1, 1, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}')),
(1, 2, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}'))
ON DUPLICATE KEY UPDATE NOTHING;
INSERT INTO t_hash_tmp_0 VALUES(2, 3, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}')),
(2, 4, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}'))
ON DUPLICATE KEY UPDATE c2 = 100;
-- tmp table with primary key
-- multi insert
INSERT INTO t_hash_tmp_1 VALUES(1, 1, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}')),
(1, 2, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}'))
ON DUPLICATE KEY UPDATE NOTHING;
INSERT INTO t_hash_tmp_1 VALUES(2, 3, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}')),
(2, 4, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}'))
ON DUPLICATE KEY UPDATE c1 = EXCLUDED.c1, c3 = EXCLUDED.c3, c4 = EXCLUDED.c4, c5 = EXCLUDED.c5, c6 = EXCLUDED.c6, c7 = EXCLUDED.c7;
SELECT * FROM t_hash_tmp_1 ORDER BY c2;
c1 | c2 | c3 | c4 | c5 | c6 | c7
----+----+----+---------+------------------+---------+-----------------------------
1 | 1 | C3 | {1,2,3} | {10,20,30,40,50} | (10,20) | (100,"(10,20)","{100,200}")
1 | 2 | C3 | {1,2,3} | {10,20,30,40,50} | (10,20) | (100,"(10,20)","{100,200}")
2 | 3 | C3 | {1,2,3} | {10,20,30,40,50} | (10,20) | (100,"(10,20)","{100,200}")
2 | 4 | C3 | {1,2,3} | {10,20,30,40,50} | (10,20) | (100,"(10,20)","{100,200}")
(4 rows)
INSERT INTO t_hash_tmp_1 VALUES(10, 1, 'C30', '{10,20,30}', '{100,200,300,400,500}', ROW(100,200), ROW(1000, ROW(100,200), '{1000,2000}')),
(11, 2, 'C31', '{11,21,31}', '{101,201,301,401,501}', ROW(101,201), ROW(1001, ROW(101,201), '{1001,2001}'))
ON DUPLICATE KEY UPDATE NOTHING;
INSERT INTO t_hash_tmp_1 VALUES(20, 3, 'C30', '{10,20,30}', '{10,20,30,40,50}', ROW(100,200), ROW(1000, ROW(100,200), '{1000,2000}')),
(21, 4, 'C31', '{11,21,31}', '{101,201,301,401,501}', ROW(101,201), ROW(1001, ROW(101,201), '{1001,2001}'))
ON DUPLICATE KEY UPDATE c1 = EXCLUDED.c1, c3 = EXCLUDED.c3, c4 = EXCLUDED.c4, c5 = EXCLUDED.c5, c6 = EXCLUDED.c6, c7 = EXCLUDED.c7;
SELECT * FROM t_hash_tmp_1 ORDER BY c2;
c1 | c2 | c3 | c4 | c5 | c6 | c7
----+----+-----+------------+-----------------------+-----------+----------------------------------
1 | 1 | C3 | {1,2,3} | {10,20,30,40,50} | (10,20) | (100,"(10,20)","{100,200}")
1 | 2 | C3 | {1,2,3} | {10,20,30,40,50} | (10,20) | (100,"(10,20)","{100,200}")
20 | 3 | C30 | {10,20,30} | {10,20,30,40,50} | (100,200) | (1000,"(100,200)","{1000,2000}")
21 | 4 | C31 | {11,21,31} | {101,201,301,401,501} | (101,201) | (1001,"(101,201)","{1001,2001}")
(4 rows)
-- insert and update same tuple, and update twice for another same tuple
INSERT INTO t_hash_tmp_1 VALUES(0, 5, 'C30', '{10,20,30}', '{10,20,30,40,50}', ROW(100,200), ROW(1000, ROW(100,200), '{1000,2000}')),
(1, 5, 'C31', '{11,21,31}', '{101,201,301,401,501}', ROW(101,201), ROW(1001, ROW(101,201), '{1001,2001}')),
(10, 1, 'C30', '{10,20,30}', '{100,200,300,400,500}', ROW(100,200), ROW(1000, ROW(100,200), '{1000,2000}')),
(11, 1, 'C31', '{11,21,31}', '{101,201,301,401,501}', ROW(101,201), ROW(1001, ROW(101,201), '{1001,2001}'))
ON DUPLICATE KEY UPDATE NOTHING;
SELECT * FROM t_hash_tmp_1 ORDER BY c2;
c1 | c2 | c3 | c4 | c5 | c6 | c7
----+----+-----+------------+-----------------------+-----------+----------------------------------
1 | 1 | C3 | {1,2,3} | {10,20,30,40,50} | (10,20) | (100,"(10,20)","{100,200}")
1 | 2 | C3 | {1,2,3} | {10,20,30,40,50} | (10,20) | (100,"(10,20)","{100,200}")
20 | 3 | C30 | {10,20,30} | {10,20,30,40,50} | (100,200) | (1000,"(100,200)","{1000,2000}")
21 | 4 | C31 | {11,21,31} | {101,201,301,401,501} | (101,201) | (1001,"(101,201)","{1001,2001}")
0 | 5 | C30 | {10,20,30} | {10,20,30,40,50} | (100,200) | (1000,"(100,200)","{1000,2000}")
(5 rows)
INSERT INTO t_hash_tmp_1 VALUES(0, 5, 'C30', '{10,20,30}', '{10,20,30,40,50}', ROW(100,200), ROW(1000, ROW(100,200), '{1000,2000}')),
(1, 5, 'C31', '{11,21,31}', '{101,201,301,401,501}', ROW(101,201), ROW(1001, ROW(101,201), '{1001,2001}')),
(10, 1, 'C30', '{10,20,30}', '{100,200,300,400,500}', ROW(100,200), ROW(1000, ROW(100,200), '{1000,2000}')),
(11, 1, 'C31', '{11,21,31}', '{101,201,301,401,501}', ROW(101,201), ROW(1001, ROW(101,201), '{1001,2001}'))
ON DUPLICATE KEY UPDATE c1 = EXCLUDED.c1, c3 = EXCLUDED.c3, c4 = EXCLUDED.c4, c5 = EXCLUDED.c5, c6 = EXCLUDED.c6, c7 = EXCLUDED.c7;
SELECT * FROM t_hash_tmp_1 ORDER BY c2;
c1 | c2 | c3 | c4 | c5 | c6 | c7
----+----+-----+------------+-----------------------+-----------+----------------------------------
11 | 1 | C31 | {11,21,31} | {101,201,301,401,501} | (101,201) | (1001,"(101,201)","{1001,2001}")
1 | 2 | C3 | {1,2,3} | {10,20,30,40,50} | (10,20) | (100,"(10,20)","{100,200}")
20 | 3 | C30 | {10,20,30} | {10,20,30,40,50} | (100,200) | (1000,"(100,200)","{1000,2000}")
21 | 4 | C31 | {11,21,31} | {101,201,301,401,501} | (101,201) | (1001,"(101,201)","{1001,2001}")
1 | 5 | C31 | {11,21,31} | {101,201,301,401,501} | (101,201) | (1001,"(101,201)","{1001,2001}")
(5 rows)
-- replication table
-- tmp table without primary key
INSERT INTO t_rep_tmp_0 VALUES(1, 1, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}')),
(1, 2, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}'))
ON DUPLICATE KEY UPDATE NOTHING;
INSERT INTO t_rep_tmp_0 VALUES(2, 3, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}')),
(2, 4, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}'))
ON DUPLICATE KEY UPDATE c2 = 100;
-- tmp table with primary key
-- multi insert
INSERT INTO t_rep_tmp_1 VALUES(1, 1, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}')),
(1, 2, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}'))
ON DUPLICATE KEY UPDATE NOTHING;
INSERT INTO t_rep_tmp_1 VALUES(2, 3, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}')),
(2, 4, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}'))
ON DUPLICATE KEY UPDATE c1 = EXCLUDED.c1, c3 = EXCLUDED.c3, c4 = EXCLUDED.c4, c5 = EXCLUDED.c5, c6 = EXCLUDED.c6, c7 = EXCLUDED.c7;
SELECT * FROM t_rep_tmp_1 ORDER BY c2;
c1 | c2 | c3 | c4 | c5 | c6 | c7
----+----+----+---------+------------------+---------+-----------------------------
1 | 1 | C3 | {1,2,3} | {10,20,30,40,50} | (10,20) | (100,"(10,20)","{100,200}")
1 | 2 | C3 | {1,2,3} | {10,20,30,40,50} | (10,20) | (100,"(10,20)","{100,200}")
2 | 3 | C3 | {1,2,3} | {10,20,30,40,50} | (10,20) | (100,"(10,20)","{100,200}")
2 | 4 | C3 | {1,2,3} | {10,20,30,40,50} | (10,20) | (100,"(10,20)","{100,200}")
(4 rows)
INSERT INTO t_rep_tmp_1 VALUES(10, 1, 'C30', '{10,20,30}', '{100,200,300,400,500}', ROW(100,200), ROW(1000, ROW(100,200), '{1000,2000}')),
(11, 2, 'C31', '{11,21,31}', '{101,201,301,401,501}', ROW(101,201), ROW(1001, ROW(101,201), '{1001,2001}'))
ON DUPLICATE KEY UPDATE NOTHING;
INSERT INTO t_rep_tmp_1 VALUES(20, 3, 'C30', '{10,20,30}', '{10,20,30,40,50}', ROW(100,200), ROW(1000, ROW(100,200), '{1000,2000}')),
(21, 4, 'C31', '{11,21,31}', '{101,201,301,401,501}', ROW(101,201), ROW(1001, ROW(101,201), '{1001,2001}'))
ON DUPLICATE KEY UPDATE c1 = EXCLUDED.c1, c3 = EXCLUDED.c3, c4 = EXCLUDED.c4, c5 = EXCLUDED.c5, c6 = EXCLUDED.c6, c7 = EXCLUDED.c7;
SELECT * FROM t_rep_tmp_1 ORDER BY c2;
c1 | c2 | c3 | c4 | c5 | c6 | c7
----+----+-----+------------+-----------------------+-----------+----------------------------------
1 | 1 | C3 | {1,2,3} | {10,20,30,40,50} | (10,20) | (100,"(10,20)","{100,200}")
1 | 2 | C3 | {1,2,3} | {10,20,30,40,50} | (10,20) | (100,"(10,20)","{100,200}")
20 | 3 | C30 | {10,20,30} | {10,20,30,40,50} | (100,200) | (1000,"(100,200)","{1000,2000}")
21 | 4 | C31 | {11,21,31} | {101,201,301,401,501} | (101,201) | (1001,"(101,201)","{1001,2001}")
(4 rows)
-- insert and update same tuple, and update twice for another same tuple
INSERT INTO t_rep_tmp_1 VALUES(0, 5, 'C30', '{10,20,30}', '{10,20,30,40,50}', ROW(100,200), ROW(1000, ROW(100,200), '{1000,2000}')),
(1, 5, 'C31', '{11,21,31}', '{101,201,301,401,501}', ROW(101,201), ROW(1001, ROW(101,201), '{1001,2001}')),
(10, 1, 'C30', '{10,20,30}', '{100,200,300,400,500}', ROW(100,200), ROW(1000, ROW(100,200), '{1000,2000}')),
(11, 1, 'C31', '{11,21,31}', '{101,201,301,401,501}', ROW(101,201), ROW(1001, ROW(101,201), '{1001,2001}'))
ON DUPLICATE KEY UPDATE NOTHING;
SELECT * FROM t_rep_tmp_1 ORDER BY c2;
c1 | c2 | c3 | c4 | c5 | c6 | c7
----+----+-----+------------+-----------------------+-----------+----------------------------------
1 | 1 | C3 | {1,2,3} | {10,20,30,40,50} | (10,20) | (100,"(10,20)","{100,200}")
1 | 2 | C3 | {1,2,3} | {10,20,30,40,50} | (10,20) | (100,"(10,20)","{100,200}")
20 | 3 | C30 | {10,20,30} | {10,20,30,40,50} | (100,200) | (1000,"(100,200)","{1000,2000}")
21 | 4 | C31 | {11,21,31} | {101,201,301,401,501} | (101,201) | (1001,"(101,201)","{1001,2001}")
0 | 5 | C30 | {10,20,30} | {10,20,30,40,50} | (100,200) | (1000,"(100,200)","{1000,2000}")
(5 rows)
INSERT INTO t_rep_tmp_1 VALUES(0, 5, 'C30', '{10,20,30}', '{10,20,30,40,50}', ROW(100,200), ROW(1000, ROW(100,200), '{1000,2000}')),
(1, 5, 'C31', '{11,21,31}', '{101,201,301,401,501}', ROW(101,201), ROW(1001, ROW(101,201), '{1001,2001}')),
(10, 1, 'C30', '{10,20,30}', '{100,200,300,400,500}', ROW(100,200), ROW(1000, ROW(100,200), '{1000,2000}')),
(11, 1, 'C31', '{11,21,31}', '{101,201,301,401,501}', ROW(101,201), ROW(1001, ROW(101,201), '{1001,2001}'))
ON DUPLICATE KEY UPDATE c1 = EXCLUDED.c1, c3 = EXCLUDED.c3, c4 = EXCLUDED.c4, c5 = EXCLUDED.c5, c6 = EXCLUDED.c6, c7 = EXCLUDED.c7;
SELECT * FROM t_rep_tmp_1 ORDER BY c2;
c1 | c2 | c3 | c4 | c5 | c6 | c7
----+----+-----+------------+-----------------------+-----------+----------------------------------
11 | 1 | C31 | {11,21,31} | {101,201,301,401,501} | (101,201) | (1001,"(101,201)","{1001,2001}")
1 | 2 | C3 | {1,2,3} | {10,20,30,40,50} | (10,20) | (100,"(10,20)","{100,200}")
20 | 3 | C30 | {10,20,30} | {10,20,30,40,50} | (100,200) | (1000,"(100,200)","{1000,2000}")
21 | 4 | C31 | {11,21,31} | {101,201,301,401,501} | (101,201) | (1001,"(101,201)","{1001,2001}")
1 | 5 | C31 | {11,21,31} | {101,201,301,401,501} | (101,201) | (1001,"(101,201)","{1001,2001}")
(5 rows)
DROP SCHEMA upsert_test_tmp CASCADE;
NOTICE: drop cascades to 10 other objects
DETAIL: drop cascades to type atype
drop cascades to table t_hash_tmp_0 column c6
drop cascades to table t_hash_tmp_1 column c6
drop cascades to table t_rep_tmp_0 column c6
drop cascades to table t_rep_tmp_1 column c6
drop cascades to type btype
drop cascades to table t_hash_tmp_0 column c7
drop cascades to table t_hash_tmp_1 column c7
drop cascades to table t_rep_tmp_0 column c7
drop cascades to table t_rep_tmp_1 column c7

View File

@ -0,0 +1,148 @@
\c upsert
SET CURRENT_SCHEMA TO upsert_test;
-- enable_upsert_to_merge must be off, or upsert will be translated to merge.
SET enable_upsert_to_merge TO OFF;
SHOW enable_upsert_to_merge;
enable_upsert_to_merge
------------------------
off
(1 row)
CREATE FUNCTION upsert_before_func()
RETURNS TRIGGER language plpgsql AS
$$
BEGIN
IF (TG_OP = 'UPDATE') THEN
RAISE warning 'before update (old): %', old.*::TEXT;
RAISE warning 'before update (new): %', new.*::TEXT;
elsIF (TG_OP = 'INSERT') THEN
RAISE warning 'before insert (new): %', new.*::TEXT;
IF NEW.key % 2 = 0 THEN
NEW.color := NEW.color || ' trig modified';
RAISE warning 'before insert (new, modified): %', new.*::TEXT;
END IF;
END IF;
RETURN new;
END;
$$;
CREATE TRIGGER upsert_before_trig BEFORE INSERT OR UPDATE ON t_trigger
FOR EACH ROW EXECUTE procedure upsert_before_func();
CREATE FUNCTION upsert_after_func()
RETURNS TRIGGER language plpgsql AS
$$
BEGIN
IF (TG_OP = 'UPDATE') THEN
RAISE warning 'after update (old): %', old.*::TEXT;
RAISE warning 'after update (new): %', new.*::TEXT;
elsIF (TG_OP = 'INSERT') THEN
RAISE warning 'after insert (new): %', new.*::TEXT;
END IF;
RETURN null;
END;
$$;
CREATE TRIGGER upsert_after_trig AFTER INSERT OR UPDATE ON t_trigger
FOR EACH ROW EXECUTE procedure upsert_after_func();
INSERT INTO t_trigger values(1, 'black') ON DUPLICATE KEY UPDATE color = 'updated ' || t_trigger.color;
WARNING: before insert (new): (1,black)
WARNING: after insert (new): (1,black)
INSERT INTO t_trigger values(2, 'red') ON DUPLICATE KEY UPDATE color = 'updated ' || t_trigger.color;
WARNING: before insert (new): (2,red)
WARNING: before insert (new, modified): (2,"red trig modified")
WARNING: after insert (new): (2,"red trig modified")
INSERT INTO t_trigger values(3, 'orange') ON DUPLICATE KEY UPDATE color = 'updated ' || t_trigger.color;
WARNING: before insert (new): (3,orange)
WARNING: after insert (new): (3,orange)
INSERT INTO t_trigger values(4, 'green') ON DUPLICATE KEY UPDATE color = 'updated ' || t_trigger.color;
WARNING: before insert (new): (4,green)
WARNING: before insert (new, modified): (4,"green trig modified")
WARNING: after insert (new): (4,"green trig modified")
INSERT INTO t_trigger values(5, 'purple') ON DUPLICATE KEY UPDATE color = 'updated ' || t_trigger.color;
WARNING: before insert (new): (5,purple)
WARNING: after insert (new): (5,purple)
INSERT INTO t_trigger values(6, 'white') ON DUPLICATE KEY UPDATE color = 'updated ' || t_trigger.color;
WARNING: before insert (new): (6,white)
WARNING: before insert (new, modified): (6,"white trig modified")
WARNING: after insert (new): (6,"white trig modified")
INSERT INTO t_trigger values(7, 'pink') ON DUPLICATE KEY UPDATE color = 'updated ' || t_trigger.color;
WARNING: before insert (new): (7,pink)
WARNING: after insert (new): (7,pink)
INSERT INTO t_trigger values(8, 'yellow') ON DUPLICATE KEY UPDATE color = 'updated ' || t_trigger.color;
WARNING: before insert (new): (8,yellow)
WARNING: before insert (new, modified): (8,"yellow trig modified")
WARNING: after insert (new): (8,"yellow trig modified")
SELECT * FROM t_trigger ORDER BY key;
key | color
-----+----------------------
1 | black
2 | red trig modified
3 | orange
4 | green trig modified
5 | purple
6 | white trig modified
7 | pink
8 | yellow trig modified
(8 rows)
INSERT INTO t_trigger values(2, 'black') ON DUPLICATE KEY UPDATE color = 'updated ' || t_trigger.color;
WARNING: before insert (new): (2,black)
WARNING: before insert (new, modified): (2,"black trig modified")
WARNING: before update (old): (2,"red trig modified")
WARNING: before update (new): (2,"updated red trig modified")
WARNING: after update (old): (2,"red trig modified")
WARNING: after update (new): (2,"updated red trig modified")
INSERT INTO t_trigger values(3, 'red') ON DUPLICATE KEY UPDATE color = 'updated ' || t_trigger.color;
WARNING: before insert (new): (3,red)
WARNING: before update (old): (3,orange)
WARNING: before update (new): (3,"updated orange")
WARNING: after update (old): (3,orange)
WARNING: after update (new): (3,"updated orange")
INSERT INTO t_trigger values(4, 'orange') ON DUPLICATE KEY UPDATE color = 'updated ' || t_trigger.color;
WARNING: before insert (new): (4,orange)
WARNING: before insert (new, modified): (4,"orange trig modified")
WARNING: before update (old): (4,"green trig modified")
WARNING: before update (new): (4,"updated green trig modified")
WARNING: after update (old): (4,"green trig modified")
WARNING: after update (new): (4,"updated green trig modified")
INSERT INTO t_trigger values(5, 'green') ON DUPLICATE KEY UPDATE color = 'updated ' || t_trigger.color;
WARNING: before insert (new): (5,green)
WARNING: before update (old): (5,purple)
WARNING: before update (new): (5,"updated purple")
WARNING: after update (old): (5,purple)
WARNING: after update (new): (5,"updated purple")
INSERT INTO t_trigger values(6, 'purple') ON DUPLICATE KEY UPDATE color = 'updated ' || t_trigger.color;
WARNING: before insert (new): (6,purple)
WARNING: before insert (new, modified): (6,"purple trig modified")
WARNING: before update (old): (6,"white trig modified")
WARNING: before update (new): (6,"updated white trig modified")
WARNING: after update (old): (6,"white trig modified")
WARNING: after update (new): (6,"updated white trig modified")
INSERT INTO t_trigger values(7, 'white') ON DUPLICATE KEY UPDATE color = 'updated ' || t_trigger.color;
WARNING: before insert (new): (7,white)
WARNING: before update (old): (7,pink)
WARNING: before update (new): (7,"updated pink")
WARNING: after update (old): (7,pink)
WARNING: after update (new): (7,"updated pink")
INSERT INTO t_trigger values(8, 'pink') ON DUPLICATE KEY UPDATE color = 'updated ' || t_trigger.color;
WARNING: before insert (new): (8,pink)
WARNING: before insert (new, modified): (8,"pink trig modified")
WARNING: before update (old): (8,"yellow trig modified")
WARNING: before update (new): (8,"updated yellow trig modified")
WARNING: after update (old): (8,"yellow trig modified")
WARNING: after update (new): (8,"updated yellow trig modified")
INSERT INTO t_trigger values(9, 'yellow') ON DUPLICATE KEY UPDATE color = 'updated ' || t_trigger.color;
WARNING: before insert (new): (9,yellow)
WARNING: after insert (new): (9,yellow)
SELECT * FROM t_trigger ORDER BY key;
key | color
-----+------------------------------
1 | black
2 | updated red trig modified
3 | updated orange
4 | updated green trig modified
5 | updated purple
6 | updated white trig modified
7 | updated pink
8 | updated yellow trig modified
9 | yellow
(9 rows)

View File

@ -0,0 +1,152 @@
\c upsert
SET CURRENT_SCHEMA TO upsert_test_unlog;
-- enable_upsert_to_merge must be off, or upsert will be translated to merge.
SET enable_upsert_to_merge TO OFF;
SHOW enable_upsert_to_merge;
enable_upsert_to_merge
------------------------
off
(1 row)
-- hash table
-- unlogged table without primary key
INSERT INTO t_hash_unlog_0 VALUES(1, 1, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}')),
(1, 2, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}'))
ON DUPLICATE KEY UPDATE NOTHING;
INSERT INTO t_hash_unlog_0 VALUES(2, 3, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}')),
(2, 4, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}'))
ON DUPLICATE KEY UPDATE c2 = 100;
-- unlogged table with primary key
-- multi insert
INSERT INTO t_hash_unlog_1 VALUES(1, 1, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}')),
(1, 2, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}'))
ON DUPLICATE KEY UPDATE NOTHING;
INSERT INTO t_hash_unlog_1 VALUES(2, 3, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}')),
(2, 4, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}'))
ON DUPLICATE KEY UPDATE c1 = EXCLUDED.c1, c3 = EXCLUDED.c3, c4 = EXCLUDED.c4, c5 = EXCLUDED.c5, c6 = EXCLUDED.c6, c7 = EXCLUDED.c7;
SELECT * FROM t_hash_unlog_1 ORDER BY c2;
c1 | c2 | c3 | c4 | c5 | c6 | c7
----+----+----+---------+------------------+---------+-----------------------------
1 | 1 | C3 | {1,2,3} | {10,20,30,40,50} | (10,20) | (100,"(10,20)","{100,200}")
1 | 2 | C3 | {1,2,3} | {10,20,30,40,50} | (10,20) | (100,"(10,20)","{100,200}")
2 | 3 | C3 | {1,2,3} | {10,20,30,40,50} | (10,20) | (100,"(10,20)","{100,200}")
2 | 4 | C3 | {1,2,3} | {10,20,30,40,50} | (10,20) | (100,"(10,20)","{100,200}")
(4 rows)
INSERT INTO t_hash_unlog_1 VALUES(10, 1, 'C30', '{10,20,30}', '{100,200,300,400,500}', ROW(100,200), ROW(1000, ROW(100,200), '{1000,2000}')),
(11, 2, 'C31', '{11,21,31}', '{101,201,301,401,501}', ROW(101,201), ROW(1001, ROW(101,201), '{1001,2001}'))
ON DUPLICATE KEY UPDATE NOTHING;
INSERT INTO t_hash_unlog_1 VALUES(20, 3, 'C30', '{10,20,30}', '{10,20,30,40,50}', ROW(100,200), ROW(1000, ROW(100,200), '{1000,2000}')),
(21, 4, 'C31', '{11,21,31}', '{101,201,301,401,501}', ROW(101,201), ROW(1001, ROW(101,201), '{1001,2001}'))
ON DUPLICATE KEY UPDATE c1 = EXCLUDED.c1, c3 = EXCLUDED.c3, c4 = EXCLUDED.c4, c5 = EXCLUDED.c5, c6 = EXCLUDED.c6, c7 = EXCLUDED.c7;
SELECT * FROM t_hash_unlog_1 ORDER BY c2;
c1 | c2 | c3 | c4 | c5 | c6 | c7
----+----+-----+------------+-----------------------+-----------+----------------------------------
1 | 1 | C3 | {1,2,3} | {10,20,30,40,50} | (10,20) | (100,"(10,20)","{100,200}")
1 | 2 | C3 | {1,2,3} | {10,20,30,40,50} | (10,20) | (100,"(10,20)","{100,200}")
20 | 3 | C30 | {10,20,30} | {10,20,30,40,50} | (100,200) | (1000,"(100,200)","{1000,2000}")
21 | 4 | C31 | {11,21,31} | {101,201,301,401,501} | (101,201) | (1001,"(101,201)","{1001,2001}")
(4 rows)
-- insert and update same tuple, and update twice for another same tuple
INSERT INTO t_hash_unlog_1 VALUES(0, 5, 'C30', '{10,20,30}', '{10,20,30,40,50}', ROW(100,200), ROW(1000, ROW(100,200), '{1000,2000}')),
(1, 5, 'C31', '{11,21,31}', '{101,201,301,401,501}', ROW(101,201), ROW(1001, ROW(101,201), '{1001,2001}')),
(10, 1, 'C30', '{10,20,30}', '{100,200,300,400,500}', ROW(100,200), ROW(1000, ROW(100,200), '{1000,2000}')),
(11, 1, 'C31', '{11,21,31}', '{101,201,301,401,501}', ROW(101,201), ROW(1001, ROW(101,201), '{1001,2001}'))
ON DUPLICATE KEY UPDATE NOTHING;
SELECT * FROM t_hash_unlog_1 ORDER BY c2;
c1 | c2 | c3 | c4 | c5 | c6 | c7
----+----+-----+------------+-----------------------+-----------+----------------------------------
1 | 1 | C3 | {1,2,3} | {10,20,30,40,50} | (10,20) | (100,"(10,20)","{100,200}")
1 | 2 | C3 | {1,2,3} | {10,20,30,40,50} | (10,20) | (100,"(10,20)","{100,200}")
20 | 3 | C30 | {10,20,30} | {10,20,30,40,50} | (100,200) | (1000,"(100,200)","{1000,2000}")
21 | 4 | C31 | {11,21,31} | {101,201,301,401,501} | (101,201) | (1001,"(101,201)","{1001,2001}")
0 | 5 | C30 | {10,20,30} | {10,20,30,40,50} | (100,200) | (1000,"(100,200)","{1000,2000}")
(5 rows)
INSERT INTO t_hash_unlog_1 VALUES(0, 5, 'C30', '{10,20,30}', '{10,20,30,40,50}', ROW(100,200), ROW(1000, ROW(100,200), '{1000,2000}')),
(1, 5, 'C31', '{11,21,31}', '{101,201,301,401,501}', ROW(101,201), ROW(1001, ROW(101,201), '{1001,2001}')),
(10, 1, 'C30', '{10,20,30}', '{100,200,300,400,500}', ROW(100,200), ROW(1000, ROW(100,200), '{1000,2000}')),
(11, 1, 'C31', '{11,21,31}', '{101,201,301,401,501}', ROW(101,201), ROW(1001, ROW(101,201), '{1001,2001}'))
ON DUPLICATE KEY UPDATE c1 = EXCLUDED.c1, c3 = EXCLUDED.c3, c4 = EXCLUDED.c4, c5 = EXCLUDED.c5, c6 = EXCLUDED.c6, c7 = EXCLUDED.c7;
SELECT * FROM t_hash_unlog_1 ORDER BY c2;
c1 | c2 | c3 | c4 | c5 | c6 | c7
----+----+-----+------------+-----------------------+-----------+----------------------------------
11 | 1 | C31 | {11,21,31} | {101,201,301,401,501} | (101,201) | (1001,"(101,201)","{1001,2001}")
1 | 2 | C3 | {1,2,3} | {10,20,30,40,50} | (10,20) | (100,"(10,20)","{100,200}")
20 | 3 | C30 | {10,20,30} | {10,20,30,40,50} | (100,200) | (1000,"(100,200)","{1000,2000}")
21 | 4 | C31 | {11,21,31} | {101,201,301,401,501} | (101,201) | (1001,"(101,201)","{1001,2001}")
1 | 5 | C31 | {11,21,31} | {101,201,301,401,501} | (101,201) | (1001,"(101,201)","{1001,2001}")
(5 rows)
-- replication table
-- unlogged table without primary key
INSERT INTO t_rep_unlog_0 VALUES(1, 1, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}')),
(1, 2, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}'))
ON DUPLICATE KEY UPDATE NOTHING;
INSERT INTO t_rep_unlog_0 VALUES(2, 3, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}')),
(2, 4, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}'))
ON DUPLICATE KEY UPDATE c2 = 100;
-- unlogged table with primary key
-- multi insert
INSERT INTO t_rep_unlog_1 VALUES(1, 1, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}')),
(1, 2, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}'))
ON DUPLICATE KEY UPDATE NOTHING;
INSERT INTO t_rep_unlog_1 VALUES(2, 3, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}')),
(2, 4, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}'))
ON DUPLICATE KEY UPDATE c1 = EXCLUDED.c1, c3 = EXCLUDED.c3, c4 = EXCLUDED.c4, c5 = EXCLUDED.c5, c6 = EXCLUDED.c6, c7 = EXCLUDED.c7;
SELECT * FROM t_rep_unlog_1 ORDER BY c2;
c1 | c2 | c3 | c4 | c5 | c6 | c7
----+----+----+---------+------------------+---------+-----------------------------
1 | 1 | C3 | {1,2,3} | {10,20,30,40,50} | (10,20) | (100,"(10,20)","{100,200}")
1 | 2 | C3 | {1,2,3} | {10,20,30,40,50} | (10,20) | (100,"(10,20)","{100,200}")
2 | 3 | C3 | {1,2,3} | {10,20,30,40,50} | (10,20) | (100,"(10,20)","{100,200}")
2 | 4 | C3 | {1,2,3} | {10,20,30,40,50} | (10,20) | (100,"(10,20)","{100,200}")
(4 rows)
INSERT INTO t_rep_unlog_1 VALUES(10, 1, 'C30', '{10,20,30}', '{100,200,300,400,500}', ROW(100,200), ROW(1000, ROW(100,200), '{1000,2000}')),
(11, 2, 'C31', '{11,21,31}', '{101,201,301,401,501}', ROW(101,201), ROW(1001, ROW(101,201), '{1001,2001}'))
ON DUPLICATE KEY UPDATE NOTHING;
INSERT INTO t_rep_unlog_1 VALUES(20, 3, 'C30', '{10,20,30}', '{10,20,30,40,50}', ROW(100,200), ROW(1000, ROW(100,200), '{1000,2000}')),
(21, 4, 'C31', '{11,21,31}', '{101,201,301,401,501}', ROW(101,201), ROW(1001, ROW(101,201), '{1001,2001}'))
ON DUPLICATE KEY UPDATE c1 = EXCLUDED.c1, c3 = EXCLUDED.c3, c4 = EXCLUDED.c4, c5 = EXCLUDED.c5, c6 = EXCLUDED.c6, c7 = EXCLUDED.c7;
SELECT * FROM t_rep_unlog_1 ORDER BY c2;
c1 | c2 | c3 | c4 | c5 | c6 | c7
----+----+-----+------------+-----------------------+-----------+----------------------------------
1 | 1 | C3 | {1,2,3} | {10,20,30,40,50} | (10,20) | (100,"(10,20)","{100,200}")
1 | 2 | C3 | {1,2,3} | {10,20,30,40,50} | (10,20) | (100,"(10,20)","{100,200}")
20 | 3 | C30 | {10,20,30} | {10,20,30,40,50} | (100,200) | (1000,"(100,200)","{1000,2000}")
21 | 4 | C31 | {11,21,31} | {101,201,301,401,501} | (101,201) | (1001,"(101,201)","{1001,2001}")
(4 rows)
-- insert and update same tuple, and update twice for another same tuple
INSERT INTO t_rep_unlog_1 VALUES(0, 5, 'C30', '{10,20,30}', '{10,20,30,40,50}', ROW(100,200), ROW(1000, ROW(100,200), '{1000,2000}')),
(1, 5, 'C31', '{11,21,31}', '{101,201,301,401,501}', ROW(101,201), ROW(1001, ROW(101,201), '{1001,2001}')),
(10, 1, 'C30', '{10,20,30}', '{100,200,300,400,500}', ROW(100,200), ROW(1000, ROW(100,200), '{1000,2000}')),
(11, 1, 'C31', '{11,21,31}', '{101,201,301,401,501}', ROW(101,201), ROW(1001, ROW(101,201), '{1001,2001}'))
ON DUPLICATE KEY UPDATE NOTHING;
SELECT * FROM t_rep_unlog_1 ORDER BY c2;
c1 | c2 | c3 | c4 | c5 | c6 | c7
----+----+-----+------------+-----------------------+-----------+----------------------------------
1 | 1 | C3 | {1,2,3} | {10,20,30,40,50} | (10,20) | (100,"(10,20)","{100,200}")
1 | 2 | C3 | {1,2,3} | {10,20,30,40,50} | (10,20) | (100,"(10,20)","{100,200}")
20 | 3 | C30 | {10,20,30} | {10,20,30,40,50} | (100,200) | (1000,"(100,200)","{1000,2000}")
21 | 4 | C31 | {11,21,31} | {101,201,301,401,501} | (101,201) | (1001,"(101,201)","{1001,2001}")
0 | 5 | C30 | {10,20,30} | {10,20,30,40,50} | (100,200) | (1000,"(100,200)","{1000,2000}")
(5 rows)
INSERT INTO t_rep_unlog_1 VALUES(0, 5, 'C30', '{10,20,30}', '{10,20,30,40,50}', ROW(100,200), ROW(1000, ROW(100,200), '{1000,2000}')),
(1, 5, 'C31', '{11,21,31}', '{101,201,301,401,501}', ROW(101,201), ROW(1001, ROW(101,201), '{1001,2001}')),
(10, 1, 'C30', '{10,20,30}', '{100,200,300,400,500}', ROW(100,200), ROW(1000, ROW(100,200), '{1000,2000}')),
(11, 1, 'C31', '{11,21,31}', '{101,201,301,401,501}', ROW(101,201), ROW(1001, ROW(101,201), '{1001,2001}'))
ON DUPLICATE KEY UPDATE c1 = EXCLUDED.c1, c3 = EXCLUDED.c3, c4 = EXCLUDED.c4, c5 = EXCLUDED.c5, c6 = EXCLUDED.c6, c7 = EXCLUDED.c7;
SELECT * FROM t_rep_unlog_1 ORDER BY c2;
c1 | c2 | c3 | c4 | c5 | c6 | c7
----+----+-----+------------+-----------------------+-----------+----------------------------------
11 | 1 | C31 | {11,21,31} | {101,201,301,401,501} | (101,201) | (1001,"(101,201)","{1001,2001}")
1 | 2 | C3 | {1,2,3} | {10,20,30,40,50} | (10,20) | (100,"(10,20)","{100,200}")
20 | 3 | C30 | {10,20,30} | {10,20,30,40,50} | (100,200) | (1000,"(100,200)","{1000,2000}")
21 | 4 | C31 | {11,21,31} | {101,201,301,401,501} | (101,201) | (1001,"(101,201)","{1001,2001}")
1 | 5 | C31 | {11,21,31} | {101,201,301,401,501} | (101,201) | (1001,"(101,201)","{1001,2001}")
(5 rows)

View File

@ -227,6 +227,7 @@ select name,vartype,unit,min_val,max_val from pg_settings where name <> 'qunit_c
enable_tsdb | bool | | |
enable_twophase_commit | bool | | |
enable_upgrade_merge_lock_mode | bool | | |
enable_upsert_to_merge | bool | | |
enable_user_metric_persistent | bool | | |
enable_valuepartition_pruning | bool | | |
enable_vector_engine | bool | | |

View File

@ -44,12 +44,18 @@ test: hw_smp
# test MERGE INTO
# test INSERT UPDATE
# test INSERT UPDATE UPSERT
test: insert_update_001 insert_update_002 insert_update_003 insert_update_008 insert_update_009 insert_update_010
test: delete update namespace case select_having select_implicit
test: hw_test_operate_user
test: hw_createtbl_llt gsqlerr
test: hw_sql_llt sqlLLT
test: upsert_prepare
test: upsert_001 upsert_002 upsert_003 upsert_008 upsert_009 upsert_010
test: upsert_grammer_test_01 upsert_unlog_test upsert_tmp_test
test: upsert_grammer_test_02 upsert_restriction upsert_composite
test: upsert_trigger_test upsert_explain
test: upsert_clean
# all pass
# run tablespace by itself, and first, because it forces a checkpoint;

View File

@ -17,3 +17,11 @@ test: delete update namespace case select_having select_implicit
test: hw_test_operate_user
test: hw_createtbl_llt gsqlerr
test: hw_sql_llt sqlLLT
# test UPSERT
test: upsert_prepare
test: upsert_001 upsert_002 upsert_003 upsert_008 upsert_009 upsert_010
test: upsert_grammer_test_01 upsert_unlog_test upsert_tmp_test
test: upsert_grammer_test_02 upsert_restriction upsert_composite
test: upsert_trigger_test upsert_explain
test: upsert_clean

View File

@ -2,6 +2,10 @@ DROP SCHEMA test_insert_update_001 CASCADE;
CREATE SCHEMA test_insert_update_001;
SET CURRENT_SCHEMA TO test_insert_update_001;
-- SET enable_upsert_to_merge=ON to test the upsert implemented by merge,
-- real upsert will be tested in specialized case.
SET enable_upsert_to_merge TO ON;
-- test description
\h INSERT

View File

@ -2,6 +2,10 @@ DROP SCHEMA test_insert_update_002 CASCADE;
CREATE SCHEMA test_insert_update_002;
SET CURRENT_SCHEMA TO test_insert_update_002;
-- SET enable_upsert_to_merge=ON to test the upsert implemented by merge,
-- real upsert will be tested in specialized case.
SET enable_upsert_to_merge TO ON;
-- test t1 with no index
CREATE TABLE t1 (
col1 INT,

View File

@ -2,6 +2,10 @@ DROP SCHEMA test_insert_update_003 CASCADE;
CREATE SCHEMA test_insert_update_003;
SET CURRENT_SCHEMA TO test_insert_update_003;
-- SET enable_upsert_to_merge=ON to test the upsert implemented by merge,
-- real upsert will be tested in specialized case.
SET enable_upsert_to_merge TO ON;
-- test t4 with one primary key with three columns
CREATE TABLE t4 (
col1 INT,

View File

@ -6,6 +6,10 @@
CREATE SCHEMA test_insert_update_008;
SET current_schema = test_insert_update_008;
-- SET enable_upsert_to_merge=ON to test the upsert implemented by merge,
-- real upsert will be tested in specialized case.
SET enable_upsert_to_merge TO ON;
CREATE TABLE products_base
(
product_id INTEGER DEFAULT 0,
@ -66,9 +70,9 @@ EXPLAIN (VERBOSE on, COSTS off)
INSERT INTO products_row
SELECT product_id, product_name, category, total FROM newproducts_row
ON DUPLICATE KEY UPDATE
product_name = __unnamed_subquery_source__.product_name,
category = __unnamed_subquery_source__.category,
total = __unnamed_subquery_source__.total;
product_name = excluded.product_name,
category = excluded.category,
total = excluded.total;
EXPLAIN (VERBOSE on, COSTS off)
INSERT INTO products_row
@ -79,18 +83,18 @@ INSERT INTO products_row
FROM newproducts_row, products_row
WHERE products_row.total + newproducts_row.total < 1000
ON DUPLICATE KEY UPDATE
product_name = __unnamed_subquery_source__.product_name,
category = __unnamed_subquery_source__.category,
total = __unnamed_subquery_source__.total;
product_name = excluded.product_name,
category = excluded.category,
total = excluded.total;
EXPLAIN (VERBOSE on, COSTS off)
INSERT INTO products_row
SELECT product_id, product_name, category, total
FROM newproducts_row WHERE product_id IS NOT NULL AND product_name IS NOT NULL
ON DUPLICATE KEY UPDATE
product_name = __unnamed_subquery_source__.product_name,
category = __unnamed_subquery_source__.category,
total = __unnamed_subquery_source__.total;
product_name = excluded.product_name,
category = excluded.category,
total = excluded.total;
-- explain analyze
BEGIN;
@ -98,9 +102,9 @@ EXPLAIN (ANALYZE on, COSTS off, TIMING off)
INSERT INTO products_row
SELECT product_id, product_name, category, total FROM newproducts_row
ON DUPLICATE KEY UPDATE
product_name = __unnamed_subquery_source__.product_name,
category = __unnamed_subquery_source__.category,
total = __unnamed_subquery_source__.total;
product_name = excluded.product_name,
category = excluded.category,
total = excluded.total;
ROLLBACK;
-- explain performance
@ -110,9 +114,9 @@ EXPLAIN PERFORMANCE
INSERT INTO products_row
SELECT product_id, product_name, category, total FROM newproducts_row
ON DUPLICATE KEY UPDATE
product_name = __unnamed_subquery_source__.product_name,
category = __unnamed_subquery_source__.category,
total = __unnamed_subquery_source__.total;
product_name = excluded.product_name,
category = excluded.category,
total = excluded.total;
ROLLBACK;
\o
@ -122,9 +126,9 @@ EXPLAIN (ANALYZE on, COSTS off, TIMING off)
INSERT INTO products_row
SELECT product_id, product_name, category, total FROM newproducts_row
ON DUPLICATE KEY UPDATE
product_name = __unnamed_subquery_source__.product_name,
category = __unnamed_subquery_source__.category,
total = __unnamed_subquery_source__.total;
product_name = excluded.product_name,
category = excluded.category,
total = excluded.total;
ROLLBACK;
-- pretty mode performance
@ -135,9 +139,9 @@ EXPLAIN (VERBOSE on, COSTS off)
INSERT INTO products_row
SELECT product_id, product_name, category, total FROM newproducts_row
ON DUPLICATE KEY UPDATE
product_name = __unnamed_subquery_source__.product_name,
category = __unnamed_subquery_source__.category,
total = __unnamed_subquery_source__.total;
product_name = excluded.product_name,
category = excluded.category,
total = excluded.total;
-- explain analyze
BEGIN;
@ -145,9 +149,9 @@ EXPLAIN (ANALYZE on, COSTS off, TIMING off)
INSERT INTO products_row
SELECT product_id, product_name, category, total FROM newproducts_row
ON DUPLICATE KEY UPDATE
product_name = __unnamed_subquery_source__.product_name,
category = __unnamed_subquery_source__.category,
total = __unnamed_subquery_source__.total;
product_name = excluded.product_name,
category = excluded.category,
total = excluded.total;
ROLLBACK;
-- explain analyze
@ -156,9 +160,9 @@ EXPLAIN (ANALYZE on, COSTS off, TIMING off)
INSERT INTO products_row
SELECT product_id, product_name, category, total FROM newproducts_row
ON DUPLICATE KEY UPDATE
product_name = __unnamed_subquery_source__.product_name,
category = __unnamed_subquery_source__.category,
total = __unnamed_subquery_source__.total;
product_name = excluded.product_name,
category = excluded.category,
total = excluded.total;
ROLLBACK;
-- explain performance
@ -168,9 +172,9 @@ EXPLAIN PERFORMANCE
INSERT INTO products_row
SELECT product_id, product_name, category, total FROM newproducts_row
ON DUPLICATE KEY UPDATE
product_name = __unnamed_subquery_source__.product_name,
category = __unnamed_subquery_source__.category,
total = __unnamed_subquery_source__.total;
product_name = excluded.product_name,
category = excluded.category,
total = excluded.total;
ROLLBACK;
SET explain_perf_mode = run;
@ -180,9 +184,9 @@ EXPLAIN PERFORMANCE
INSERT INTO products_row
SELECT product_id, product_name, category, total FROM newproducts_row
ON DUPLICATE KEY UPDATE
product_name = __unnamed_subquery_source__.product_name,
category = __unnamed_subquery_source__.category,
total = __unnamed_subquery_source__.total;
product_name = excluded.product_name,
category = excluded.category,
total = excluded.total;
ROLLBACK;
SET explain_perf_mode = summary;
@ -192,9 +196,9 @@ EXPLAIN PERFORMANCE
INSERT INTO products_row
SELECT product_id, product_name, category, total FROM newproducts_row
ON DUPLICATE KEY UPDATE
product_name = __unnamed_subquery_source__.product_name,
category = __unnamed_subquery_source__.category,
total = __unnamed_subquery_source__.total;
product_name = excluded.product_name,
category = excluded.category,
total = excluded.total;
ROLLBACK;
\o

View File

@ -2,6 +2,11 @@ DROP SCHEMA test_insert_update_009 CASCADE;
CREATE SCHEMA test_insert_update_009;
SET CURRENT_SCHEMA TO test_insert_update_009;
SET enable_light_proxy=off;
-- SET enable_upsert_to_merge=ON to test the upsert implemented by merge,
-- real upsert will be tested in specialized case.
SET enable_upsert_to_merge TO ON;
-- test t1 with no index
CREATE TABLE t1 (
col1 INT,

View File

@ -1,6 +1,11 @@
DROP SCHEMA test_insert_update_010 CASCADE;
CREATE SCHEMA test_insert_update_010;
SET CURRENT_SCHEMA TO test_insert_update_010;
-- SET enable_upsert_to_merge=ON to test the upsert implemented by merge,
-- real upsert will be tested in specialized case.
SET enable_upsert_to_merge TO ON;
-- test t4 with one primary key with three columns
CREATE TABLE t4 (
col1 INT,

View File

@ -1,3 +1,6 @@
-- SET enable_upsert_to_merge=ON to test the upsert implemented by merge,
-- real upsert will be tested in specialized case.
SET enable_upsert_to_merge TO ON;
SELECT name, setting FROM pg_settings WHERE name LIKE 'enable%' ORDER BY name;

View File

@ -0,0 +1,284 @@
DROP SCHEMA test_upsert_001 CASCADE;
CREATE SCHEMA test_upsert_001;
SET CURRENT_SCHEMA TO test_upsert_001;
-- enable_upsert_to_merge must is off, or upsert will be translated to merge.
SET enable_upsert_to_merge TO OFF;
-- test description
\h INSERT
-- test permission
--- test with no sequence column
CREATE TABLE t00 (col1 INT DEFAULT 1 PRIMARY KEY, col2 INT);
CREATE USER upsert_tester PASSWORD '123456@cc';
GRANT ALL PRIVILEGES ON SCHEMA test_upsert_001 TO upsert_tester;
SET SESSION SESSION AUTHORIZATION upsert_tester PASSWORD '123456@cc';
INSERT INTO test_upsert_001.t00 VALUES(1) ON DUPLICATE KEY UPDATE col2 = 5;
RESET SESSION AUTHORIZATION;
---- error: only have INSERT permission
GRANT INSERT ON test_upsert_001.t00 TO upsert_tester;
SET SESSION SESSION AUTHORIZATION upsert_tester PASSWORD '123456@cc';
INSERT INTO test_upsert_001.t00 VALUES(1) ON DUPLICATE KEY UPDATE col2 = 5;
RESET SESSION AUTHORIZATION;
---- success: have INSERT UPDATE permission
GRANT INSERT, UPDATE ON test_upsert_001.t00 TO upsert_tester;
SET SESSION SESSION AUTHORIZATION upsert_tester PASSWORD '123456@cc';
INSERT INTO test_upsert_001.t00 VALUES(1) ON DUPLICATE KEY UPDATE col2 = 5;
RESET SESSION AUTHORIZATION;
--- have SELECT INSERT UPDATE permission
GRANT SELECT, INSERT, UPDATE ON test_upsert_001.t00 TO upsert_tester;
SET SESSION SESSION AUTHORIZATION upsert_tester PASSWORD '123456@cc';
INSERT INTO test_upsert_001.t00 VALUES(1) ON DUPLICATE KEY UPDATE col2 = 5;
INSERT INTO test_upsert_001.t00 VALUES(1) ON DUPLICATE KEY UPDATE col3 = 5;
RESET SESSION AUTHORIZATION;
--- test with sequnce column
CREATE TABLE t01 (col1 INT , col2 BIGSERIAL PRIMARY KEY, col3 INT) ;
---- error: don't have UPDATE permission on sequence table.
GRANT SELECT, INSERT, UPDATE ON test_upsert_001.t01 TO upsert_tester;
SET SESSION SESSION AUTHORIZATION upsert_tester PASSWORD '123456@cc';
INSERT INTO test_upsert_001.t01 VALUES(1) ON DUPLICATE KEY UPDATE col3 = 5;
RESET SESSION AUTHORIZATION;
---- have SELECT INSERT UPDATE permission on target relation, and UPDATE permission on sequence table.
GRANT UPDATE ON test_upsert_001.t01_col2_seq TO upsert_tester;
SET SESSION SESSION AUTHORIZATION upsert_tester PASSWORD '123456@cc';
INSERT INTO test_upsert_001.t01 VALUES(1) ON DUPLICATE KEY UPDATE col3 = 5;
INSERT INTO test_upsert_001.t01 VALUES(1) ON DUPLICATE KEY UPDATE col3 = 5;
RESET SESSION AUTHORIZATION;
-- test ommit INSERT target column
CREATE TABLE t02 (col1 INT DEFAULT 1 PRIMARY KEY, col2 INT, col3 INT);
INSERT INTO t02 VALUES(1, 2, 3) ON DUPLICATE KEY UPDATE col2 = 20;
SELECT * FROM t02 ORDER BY 1, 2;
INSERT INTO t02 VALUES(1, 2, 3) ON DUPLICATE KEY UPDATE col2 = 20;
SELECT * FROM t02 ORDER BY 1, 2;
ALTER TABLE t02 DROP COLUMN col2;
ALTER TABLE t02 ADD COLUMN col4 INT;
INSERT INTO t02 VALUES(1, 2, 3) ON DUPLICATE KEY UPDATE col4 = 40;
SELECT * FROM t02 ORDER BY 1, 2;
INSERT INTO t02 VALUES(2, 3, 4) ON DUPLICATE KEY UPDATE col4 = 40;
SELECT * FROM t02 ORDER BY 1, 2;
INSERT INTO t02 VALUES(2, 3, 4) ON DUPLICATE KEY UPDATE col4 = 40;
SELECT * FROM t02 ORDER BY 1, 2;
-- test restriction
--- test replication table
CREATE TABLE t03 (col1 int PRIMARY KEY, col2 INT, col3 smallserial) ;
--- error: not allowed volatile function as default value
INSERT INTO t03(col2) VALUES(1) ON DUPLICATE KEY UPDATE col2 = 100;
ALTER TABLE t03 DROP COLUMN col3;
--- error: primary key are not allowed to update
INSERT INTO t03 VALUES(1) ON DUPLICATE KEY UPDATE col1 = 1;
--- error: clause other than VALUSES are not allowed to use
INSERT INTO t03 SELECT * FROM t03 ON DUPLICATE KEY UPDATE col2 = 1;
--- success: expression index are supported
CREATE UNIQUE INDEX u_expr_index ON t03 USING btree (abs(col1));
INSERT INTO t03 VALUES(-10, 10) ON DUPLICATE KEY UPDATE col2 = 20;
DROP INDEX u_expr_index;
-- test with stream operator on
INSERT INTO t03 VALUES(1) ON DUPLICATE KEY UPDATE col2 = 100;
SELECT * FROM t03;
INSERT INTO t03 VALUES(1) ON DUPLICATE KEY UPDATE col2 = 100;
SELECT * FROM t03;
SELECT * FROM t03;
--- test PBE
PREPARE p1 AS INSERT INTO t03 VALUES($1, $2) ON DUPLICATE KEY UPDATE col2 = $1*100;
EXECUTE p1(5, 50);
SELECT * FROM t03 WHERE col1 = 5;
EXECUTE p1(5, 50);
SELECT * FROM t03 WHERE col1 = 5;
DELETE t03 WHERE col1 = 5;
---- test with primary key
INSERT INTO t03 VALUES(2) ON DUPLICATE KEY UPDATE col2 = 200;
SELECT * FROM t03;
INSERT INTO t03 VALUES(2) ON DUPLICATE KEY UPDATE col2 = 200;
SELECT * FROM t03;
SELECT * FROM t03;
---- test with unique key without NOT NULL constraint
ALTER TABLE t03 DROP CONSTRAINT t03_pkey;
ALTER TABLE t03 ADD COLUMN col3 INT;
CREATE UNIQUE INDEX ON t03 (col1, col3);
---- unique constraints might contain NULL, depends on the plan
----- for cn light and fqs, it can be done
INSERT INTO t03 VALUES(3) ON DUPLICATE KEY UPDATE col2 = 300;
----- for stream or pgxc it can not be done
INSERT INTO t03 VALUES(3) ON DUPLICATE KEY UPDATE col2 = 300;
---- test with unique key with NOT NULL constraint, should success
CREATE UNIQUE INDEX ON t03 (col1);
INSERT INTO t03 VALUES(3) ON DUPLICATE KEY UPDATE col2 = 300;
SELECT * FROM t03;
INSERT INTO t03 VALUES(3) ON DUPLICATE KEY UPDATE col2 = 300;
SELECT * FROM t03;
SELECT * FROM t03;
---- test PBE
PREPARE p2 AS INSERT INTO t03 VALUES($1, $2) ON DUPLICATE KEY UPDATE col2 = $1*100;
EXECUTE p2(5, 50);
SELECT * FROM t03 WHERE col1 = 5;
EXECUTE p2(5, 50);
SELECT * FROM t03 WHERE col1 = 5;
--- error: test with clause
WITH tmp(col1, col2) AS (SELECT * FROM t01)
INSERT INTO t01 SELECT * FROM tmp ON DUPLICATE KEY UPDATE col1 = 1;
WITH RECURSIVE rq AS
(
SELECT col1, col2 FROM t00 WHERE col1 = 1
UNION ALL
SELECT origin.col1, rq.col2
FROM rq JOIN t00 AS origin ON origin.col1 = rq.col1
)
INSERT INTO t03 SELECT * FROM rq ON DUPLICATE KEY UPDATE col1 = rq.col1;
--- error: test returning clause
INSERT INTO t01 VALUES (1) ON DUPLICATE KEY UPDATE col1 = 1 RETURNING NOT(1::bool);
--- error: distribute key are not allowed to UPDATE
CREATE TABLE t04 (col1 INT, col2 INT) ;
INSERT INTO t04 VALUES (1) ON DUPLICATE KEY UPDATE col1 = 5;
--- error: unique index referenced column are not allowed to UPDATE
CREATE UNIQUE INDEX t04_u_index ON t04(col1, col2);
INSERT INTO t04 VALUES (1) ON DUPLICATE KEY UPDATE col2 = 5;
DROP INDEX t04_u_index;
--- error: primary key referenced column are not allowed to UPDATE
ALTER TABLE t04 ADD PRIMARY KEY (col1, col2);
INSERT INTO t04 VALUES (1) ON DUPLICATE KEY UPDATE col2 = 5;
--- error: invalid column
INSERT INTO t04 (col2, col3) VALUES (2, 3) ON DUPLICATE KEY UPDATE col2 = 5;
--- error: duplicate column
INSERT INTO t04 (col2, col2) VALUES (2, 3) ON DUPLICATE KEY UPDATE col2 = 5;
-- error: target column more than insert target
INSERT INTO t04 (col1, col2) VALUES (2, 3, 4) ON DUPLICATE KEY UPDATE col2 = 5;
INSERT INTO t04 (col1, col2) VALUES (1) ON DUPLICATE KEY UPDATE col2 = 5;
INSERT INTO t04 (col1, col2) SELECT col1 FROM t04 ON DUPLICATE KEY UPDATE col2 = 5;
INSERT INTO t04 (col1, col2) SELECT *, col1 FROM t04 ON DUPLICATE KEY UPDATE col2 = 5;
INSERT INTO t04 VALUES (2, 3, 4) ON DUPLICATE KEY UPDATE col2 = 5;
INSERT INTO t04 VALUES (1) ON DUPLICATE KEY UPDATE col2 = 5;
INSERT INTO t04 SELECT col1 FROM t04 ON DUPLICATE KEY UPDATE col2 = 5;
INSERT INTO t04 SELECT *, col1 FROM t04 ON DUPLICATE KEY UPDATE col2 = 5;
-- test DEFAULT VALUES
TRUNCATE t00;
TRUNCATE t01;
--- without sequence
----should insert
INSERT INTO t00 DEFAULT VALUES ON DUPLICATE KEY UPDATE col2 = col1;
SELECT * FROM t00 ORDER BY 1, 2;
---- should update
INSERT INTO t00 DEFAULT VALUES ON DUPLICATE KEY UPDATE col2 = col1;
SELECT * FROM t00 ORDER BY 1, 2;
--- test drop column
TRUNCATE t00;
ALTER TABLE t00 DROP COLUMN col2;
ALTER TABLE t00 ADD COLUMN col3 INT DEFAULT 100;
----should insert
INSERT INTO t00 DEFAULT VALUES ON DUPLICATE KEY UPDATE col3 = col1;
SELECT * FROM t00 ORDER BY 1, 2;
---- should update
INSERT INTO t00 DEFAULT VALUES ON DUPLICATE KEY UPDATE col3 = col1;
SELECT * FROM t00 ORDER BY 1, 2;
--- with sequence
----should insert
INSERT INTO t01 DEFAULT VALUES ON DUPLICATE KEY UPDATE col1 = col2;
INSERT INTO t01 (col2) SELECT col2 + 1 FROM t01 LIMIT 1;
SELECT * FROM t01 ORDER BY 1, 2, 3;
---- should update
INSERT INTO t01 DEFAULT VALUES ON DUPLICATE KEY UPDATE col1 = col2;
SELECT * FROM t01 ORDER BY 1, 2, 3;
-- test VALUES(DEFAULT)
CREATE TABLE t05 (col1 INT , col2 INT DEFAULT 1 PRIMARY KEY, col3 INT DEFAULT 100) ;
--- should insert
INSERT INTO t05 VALUES(DEFAULT) ON DUPLICATE KEY UPDATE col3 = 1000;
SELECT * FROM t05 ORDER BY 1, 2, 3;
--- should update
INSERT INTO t05 VALUES(DEFAULT) ON DUPLICATE KEY UPDATE col3 = 1000;
SELECT * FROM t05 ORDER BY 1, 2, 3;
-- test UPDATE DEFAULT
INSERT INTO t05 (col1, col2, col3) VALUES (2, 2, 2) ON DUPLICATE KEY UPDATE col3 = DEFAULT;
SELECT * FROM t05 ORDER BY 1, 2, 3;
INSERT INTO t05 (col1, col2, col3) VALUES (2, 2, 2) ON DUPLICATE KEY UPDATE col3 = DEFAULT;
SELECT * FROM t05 ORDER BY 1, 2, 3;
-- test VALUES (DEFAULT, ...)
TRUNCATE t05;
--- should insert
INSERT INTO t05 VALUES(DEFAULT, DEFAULT, 200), (DEFAULT, 200, DEFAULT)
ON DUPLICATE KEY UPDATE col3 = DEFAULT, col1 = col3;
SELECT * FROM t05 ORDER BY 1, 2, 3;
--- should update
INSERT INTO t05 VALUES(DEFAULT, DEFAULT, 200), (DEFAULT, 200, DEFAULT)
ON DUPLICATE KEY UPDATE col3 = DEFAULT, col1 = col3;
SELECT * FROM t05 ORDER BY 1, 2, 3;
--- test drop coulmn
BEGIN;
ALTER TABLE t05 ADD COLUMN col4 INT;
ALTER TABLE t05 ADD COLUMN col5 INT DEFAULT 500;
ALTER TABLE t05 DROP COLUMN col3;
TRUNCATE t05;
INSERT INTO t05 VALUES(DEFAULT, DEFAULT, DEFAULT, 600) ON DUPLICATE KEY UPDATE col5 = DEFAULT;
SELECT * FROM t05 ORDER BY 1, 2, 3;
INSERT INTO t05 VALUES(DEFAULT, DEFAULT, DEFAULT, 600) ON DUPLICATE KEY UPDATE col5 = DEFAULT;
SELECT * FROM t05 ORDER BY 1, 2, 3;
ROLLBACK;
-- test schema
SET current_schema = public;
TRUNCATE test_upsert_001.t05;
--- should insert
INSERT INTO test_upsert_001.t05 VALUES(DEFAULT, DEFAULT, 200), (DEFAULT, 200, DEFAULT)
ON DUPLICATE KEY UPDATE col3 = DEFAULT, col1 = col3;
SELECT * FROM test_upsert_001.t05 ORDER BY 1, 2, 3;
--- should update
INSERT INTO test_upsert_001.t05 VALUES(DEFAULT, DEFAULT, 200), (DEFAULT, 200, DEFAULT)
ON DUPLICATE KEY UPDATE col3 = DEFAULT, col1 = col3;
SELECT * FROM test_upsert_001.t05 ORDER BY 1, 2, 3;
--- test using schema on update
INSERT INTO test_upsert_001.t05 VALUES(DEFAULT, DEFAULT, 200), (DEFAULT, 200, DEFAULT)
ON DUPLICATE KEY UPDATE t05.col3 = DEFAULT, t05.col1 = t05.col3 + 1;
SELECT * FROM test_upsert_001.t05 ORDER BY 1, 2, 3;
--- error: should not append schema
INSERT INTO test_upsert_001.t05 VALUES(DEFAULT, DEFAULT, 200), (DEFAULT, 200, DEFAULT)
ON DUPLICATE KEY UPDATE test_upsert_001.t05.col3 = DEFAULT, t05.col1 = t05.col3 + 1;
INSERT INTO test_upsert_001.t05 VALUES(DEFAULT, DEFAULT, 200), (DEFAULT, 200, DEFAULT)
ON DUPLICATE KEY UPDATE t05.col3 = DEFAULT, t05.col1 = test_upsert_001.t05.col3 + 1;
SET CURRENT_SCHEMA TO test_upsert_001;
DROP USER upsert_tester CASCADE;
DROP SCHEMA test_upsert_001 CASCADE;

View File

@ -0,0 +1,279 @@
DROP SCHEMA test_upsert_002 CASCADE;
CREATE SCHEMA test_upsert_002;
SET CURRENT_SCHEMA TO test_upsert_002;
-- enable_upsert_to_merge must is off, or upsert will be translated to merge.
SET enable_upsert_to_merge TO OFF;
-- test t1 with no index
CREATE TABLE t1 (
col1 INT,
col2 INT,
col3 INT DEFAULT 1,
-- col4 TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
col5 BIGSERIAL
) ;
INSERT INTO t1 VALUES (1, 2) ON DUPLICATE KEY UPDATE col1 = 3;
--- should always insert
INSERT INTO t1 VALUES (1, 2) ON DUPLICATE KEY UPDATE col2 = 3;
INSERT INTO t1 VALUES (1, 2) ON DUPLICATE KEY UPDATE t1.col2 = 4;
--- appoint column list in insert clause, should always insert
INSERT INTO t1(col1, col3) VALUES (1, 3) ON DUPLICATE KEY UPDATE col2 = 5;
INSERT INTO t1(col1, col3) VALUES (1, 3) ON DUPLICATE KEY UPDATE t1.col2 = 6;
--- multiple rows, should always insert
INSERT INTO t1 VALUES (2, 1), (2, 1) ON DUPLICATE KEY UPDATE col2 = 7, col3 = 7;
SELECT * FROM t1 ORDER BY col5;
--- test union, should insert
INSERT INTO t1 (col1, col2)
SELECT * FROM
(SELECT col1, col2 FROM t1
UNION
SELECT col1, col3 FROM t1) AS union_table
ON DUPLICATE KEY UPDATE col3 = (col1 + col2 + col3) * 10;
SELECT col1, col2, col3 FROM t1 WHERE col5 > 6 ORDER BY col1, col2;
--- test subquery, should insert
INSERT INTO t1
(SELECT col1 || col2 || '00' FROM t1 ORDER BY col5)
ON DUPLICATE KEY UPDATE col3 = col1 * 100;
SELECT col1, col2, col3 FROM t1 WHERE col1 >= 100 ORDER BY col1;
-- test t2 with one primary key
CREATE TABLE t2 (
col1 INT,
col2 INT PRIMARY KEY,
col3 INT DEFAULT 1,
col4 TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
col5 BIGSERIAL
) ;
--- primary key or unique key are not allowed to update
INSERT INTO t2 VALUES (1, 1) ON DUPLICATE KEY UPDATE col2 = 3;
INSERT INTO t2 VALUES (1, 1) ON DUPLICATE KEY UPDATE t2.col2 = 3;
INSERT INTO t2 (col2, col3, col4, col5)
VALUES (10, 10, CURRENT_TIMESTAMP(0), 10),
(20, 20, CURRENT_TIMESTAMP(1), 20),
(30, 30, CURRENT_TIMESTAMP(2), 30)
ON DUPLICATE KEY UPDATE
col1 = 100,
col2 = 100,
col3 = 100,
col4 = '2019-08-09'::TIMESTAMP,
col5 = 100;
--- should insert
INSERT INTO t2 VALUES (1, 1) ON DUPLICATE KEY UPDATE col1 = 30;
INSERT INTO t2 VALUES (2, 2) ON DUPLICATE KEY UPDATE t2.col1 = 40;
INSERT INTO t2 VALUES (3, 3) ON DUPLICATE KEY UPDATE col1 = col1 * 2;
INSERT INTO t2 VALUES (4, 4) ON DUPLICATE KEY UPDATE t2.col1 = t2.col1 * 2 ;
INSERT INTO t2 VALUES (5, 5) ON DUPLICATE KEY UPDATE col1 = col2 + 1;
INSERT INTO t2 VALUES (6, 6) ON DUPLICATE KEY UPDATE t2.col1 = t2.col2 + 1;
INSERT INTO t2 VALUES (7, 7) ON DUPLICATE KEY UPDATE col1 = extract(dow from col4) + 10;
INSERT INTO t2 VALUES (8, 8) ON DUPLICATE KEY UPDATE t2.col1 = extract(century from col4) * 100 + extract(isodow from col4);
SELECT col1, col2, col3, col5 FROM t2 ORDER BY col5;
--- should update
INSERT INTO t2 VALUES (3, 1) ON DUPLICATE KEY UPDATE col1 = 30, col3 = col5 + 1;
INSERT INTO t2 VALUES (4, 2) ON DUPLICATE KEY UPDATE t2.col1 = 40, t2.col3 = t2.col5;
INSERT INTO t2 VALUES (3, 3), (4, 4) ON DUPLICATE KEY UPDATE col3 = t2.col5 + 1;
INSERT INTO t2 VALUES (5, 5) ON DUPLICATE KEY UPDATE col1 = extract(dow from col4) + 10;
INSERT INTO t2 VALUES (6, 6) ON DUPLICATE KEY UPDATE t2.col1 = extract(century from col4) * 100 + extract(isodow from col4);
SELECT col1, col2, col3, col5 FROM t2 ORDER BY col5;
-- primary key are not allowed to be null
INSERT INTO t2 (col1) VALUES (10) ON DUPLICATE KEY UPDATE col1 = 10;
--- appoint column list in insert clause
---- should insert
INSERT INTO t2 (col2, col3) VALUES (9, 9) ON DUPLICATE KEY UPDATE col1 = 90;
INSERT INTO t2 (col2, col3, col4, col5)
VALUES (10, 10, CURRENT_TIMESTAMP(0), 10),
(20, 20, CURRENT_TIMESTAMP(1), 20),
(30, 30, CURRENT_TIMESTAMP(2), 30)
ON DUPLICATE KEY UPDATE
col1 = 100,
col3 = 100,
col4 = '2019-08-20'::TIMESTAMP,
col5 = 100;
SELECT * FROM t2 ORDER BY col5;
---- should update
INSERT INTO t2 (col2, col3) VALUES (9, 9) ON DUPLICATE KEY UPDATE col1 = 90;
INSERT INTO t2 (col2, col3, col4, col5)
VALUES (10, 10, CURRENT_TIMESTAMP(0), 10),
(20, 20, CURRENT_TIMESTAMP(1), 20),
(30, 30, CURRENT_TIMESTAMP(2), 30)
ON DUPLICATE KEY UPDATE
col1 = 100,
col3 = 100,
col4 = '2019-08-20'::TIMESTAMP,
col5 = 100;
SELECT * FROM t2 ORDER BY col5, col2;
--- test subquery
---- should insert
INSERT INTO t2
(SELECT col1 * 1000, col2 * 1000 + 1 FROM t2 ORDER BY col5 LIMIT 2)
ON DUPLICATE KEY UPDATE col3 = col2 + 1;
INSERT INTO t2 (col2, col3)
(SELECT col1 * 1000 + 2, col2 * 1000 FROM t2 ORDER BY col5 LIMIT 2 OFFSET 1)
ON DUPLICATE KEY UPDATE col3 = col2 + 1;
SELECT col1, col2, col3, col5 FROM t2 ORDER BY col5, col2;
---- should update
INSERT INTO t2
(SELECT col1 * 1000, col2 * 1000 + 1 FROM t2 ORDER BY col5 LIMIT 2)
ON DUPLICATE KEY UPDATE col3 = col2 + 1;
INSERT INTO t2 (col2, col3)
(SELECT col1 * 1000 + 2, col2 * 1000 FROM t2 ORDER BY col5 LIMIT 2 OFFSET 1)
ON DUPLICATE KEY UPDATE col3 = col2 + 1;
SELECT col1, col2, col3, col5 FROM t2 ORDER BY col5, col2;
--- test union, some insert some update
SELECT col1, col2 FROM t1 WHERE col2 IS NOT NULL
UNION
SELECT col1, col3 FROM t1 ORDER BY 1, 2;
INSERT INTO t2 (col1, col2)
SELECT * FROM
(SELECT col1, col2 FROM t1 WHERE col2 IS NOT NULL
UNION
SELECT col1, col3 FROM t1) AS union_table
ON DUPLICATE KEY UPDATE col3 = (col1 + col2 + col3);
SELECT col1, col2, col3, col5 FROM t2 ORDER BY col5, col2;
INSERT INTO t2 (col1, col2)
SELECT col1, col2 FROM t1 WHERE col2 IS NOT NULL
UNION
SELECT col1, col3 FROM t1
ON DUPLICATE KEY UPDATE col3 = col3 + 1;
SELECT col1, col2, col3, col5 FROM t2 ORDER BY col5, col2;
reset behavior_compat_options;
-- test INTERSECT, should update
(SELECT col1, col1 + col2 FROM t1 WHERE col2 IS NOT NULL
UNION
SELECT 1, 2)
INTERSECT
SELECT col1, col3 FROM t1;
INSERT INTO t2 (col1, col2)
(SELECT col1, col1 + col2 FROM t1 WHERE col2 IS NOT NULL
UNION
SELECT 1, 2)
INTERSECT
SELECT col1, col3 FROM t1
ON DUPLICATE KEY UPDATE col3 = col3 + 1;
SELECT col1, col2, col3, col5 FROM t2 WHERE col2 = 3 ORDER BY col5, col2;
-- test EXCEPT, should update
SELECT col1, col2 FROM t1 WHERE col2 IS NOT NULL
EXCEPT
(SELECT col1, col3 FROM t1
UNION
SELECT NULL, NULL);
INSERT INTO t2 (col1, col2)
SELECT col1, col2 FROM t1 WHERE col2 IS NOT NULL
EXCEPT
(SELECT col1, col3 FROM t1
UNION
SELECT NULL, NULL)
ON DUPLICATE KEY UPDATE col3 = col3 + 1;
SELECT col1, col2, col3, col5 FROM t2 WHERE col2 = 2 ORDER BY col5, col2;
-- test unique index with not default value
ALTER TABLE t2 DROP CONSTRAINT t2_pkey;
CREATE UNIQUE INDEX t2_u_index ON t2(col2, col5);
SELECT col1, col2 FROM t1 WHERE col2 IS NOT NULL
EXCEPT
(SELECT col1, col3 FROM t1
UNION
SELECT NULL, NULL);
INSERT INTO t2
SELECT col1, col2 FROM t1 WHERE col2 IS NOT NULL
EXCEPT
(SELECT col1, col3 FROM t1
UNION
SELECT NULL, NULL)
ON DUPLICATE KEY UPDATE col3 = col3 + 1;
SELECT col1, col2, col3, col5 FROM t2 WHERE col2 = 2 ORDER BY col5, col2;
-- test t3 with one primary index with two columns
CREATE TABLE t3 (
col1 INT,
col2 INT,
col3 INT DEFAULT 1,
-- col4 TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
col5 BIGSERIAL,
PRIMARY KEY (col2, col3)
) ;
--- column referenced by primary key are not allowed to update
INSERT INTO t3 VALUES (1, 1) ON DUPLICATE KEY UPDATE col3 = 3;
--- should insert when not contains primary key and not all primary key referred columns have default value.
--- but will fail cause primary key should not be null
INSERT INTO t3 (col1) VALUES (1) ON DUPLICATE KEY UPDATE col1 = 2;
--- should insert
--- (SEQUENCE BUG: the serial column will starts from 2 since the above statement has applied for a sequence)
INSERT INTO t3 VALUES (1, 1) ON DUPLICATE KEY UPDATE col1 = 10;
INSERT INTO t3 VALUES (2, 2, 2) ON DUPLICATE KEY UPDATE col5 = 20;
SELECT * FROM t3 order by col5;
--- should update
INSERT INTO t3 VALUES (1, 1) ON DUPLICATE KEY UPDATE col1 = 10;
INSERT INTO t3 VALUES (2, 2, 2) ON DUPLICATE KEY UPDATE col5 = 20;
SELECT * FROM t3 order by col5;
--- test subquery
---- should insert
INSERT INTO t3 (col2, col3) (SELECT max(col2) + 1, max(col3) + 1 FROM t3) ON DUPLICATE KEY UPDATE col1 = col2 + col3;
SELECT * FROM t3 order by col5;
---- should update
INSERT INTO t3 (col2, col3) (SELECT max(col2), max(col3) FROM t3) ON DUPLICATE KEY UPDATE col1 = col2 + col3;
SELECT * FROM t3 order by col5;
-- test t3 with one unique index with two columns
TRUNCATE t3;
ALTER TABLE t3 DROP CONSTRAINT t3_pkey;
ALTER TABLE t3 ALTER COLUMN col2 DROP NOT NULL;
CREATE UNIQUE INDEX t3_ukey ON t3 (col2, col3);
--- column referenced by unique key are not allowed to update
INSERT INTO t3 VALUES (1, 1) ON DUPLICATE KEY UPDATE col3 = 3;
--- should insert cause not contains unique key and not all unique key referred columns have default value.
INSERT INTO t3 (col1) VALUES (1) ON DUPLICATE KEY UPDATE col1 = 2;
INSERT INTO t3 (col1) VALUES (1) ON DUPLICATE KEY UPDATE col1 = 2;
SELECT * FROM t3 order by col5;
--- should insert
INSERT INTO t3 VALUES (1, 1) ON DUPLICATE KEY UPDATE col1 = 10;
INSERT INTO t3 VALUES (2, 2, 2) ON DUPLICATE KEY UPDATE t3.col5 = 20;
SELECT * FROM t3 ORDER BY col5;
--- should update
INSERT INTO t3 VALUES (1, 1) ON DUPLICATE KEY UPDATE t3.col1 = 10;
INSERT INTO t3 VALUES (2, 2, 2) ON DUPLICATE KEY UPDATE col5 = 20;
SELECT * FROM t3 ORDER BY col5;
--- test subquery
---- should insert
INSERT INTO t3 (SELECT 100, NULL, max(col3) FROM t3) ON DUPLICATE KEY UPDATE col1 = col2 + col3;
INSERT INTO t3 (SELECT 100, NULL, max(col3) FROM t3) ON DUPLICATE KEY UPDATE col1 = col2 + col3;
INSERT INTO t3 (col2, col3) (SELECT max(col2) + 1, max(col3) + 1 FROM t3) ON DUPLICATE KEY UPDATE col1 = col2 + col3;
SELECT * FROM t3 ORDER BY col5;
---- should update
INSERT INTO t3 (col2, col3) (SELECT max(col2), max(col3) FROM t3) ON DUPLICATE KEY UPDATE col1 = col2 + col3;
SELECT * FROM t3 ORDER BY col5;
DROP SCHEMA test_upsert_002 CASCADE;

View File

@ -0,0 +1,144 @@
DROP SCHEMA test_insert_update_003 CASCADE;
CREATE SCHEMA test_insert_update_003;
SET CURRENT_SCHEMA TO test_insert_update_003;
-- enable_upsert_to_merge must is off, or upsert will be translated to merge.
SET enable_upsert_to_merge TO OFF;
-- test t4 with one primary key with three columns
CREATE TABLE t4 (
col1 INT,
col2 INT DEFAULT 0,
col3 INT DEFAULT 1,
col4 TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
col5 BIGSERIAL,
PRIMARY KEY (col2, col3, col5)
) ;
--- should insert
INSERT INTO t4 VALUES (1) ON DUPLICATE KEY UPDATE col1 = 10;
INSERT INTO t4 VALUES (1) ON DUPLICATE KEY UPDATE col1 = 10;
INSERT INTO t4 VALUES (2, 2, 2) ON DUPLICATE KEY UPDATE col1 = 200;
INSERT INTO t4 VALUES (100, 100, 100, CURRENT_TIMESTAMP, 100) ON DUPLICATE KEY UPDATE col1 = 1000;
SELECT col1, col2, col3, col5 FROM t4 ORDER BY col5;
--- should update
INSERT INTO t4 VALUES (2, 2, 2, CURRENT_TIMESTAMP, 3) ON DUPLICATE KEY UPDATE col1 = 200;
INSERT INTO t4 VALUES (100, 100, 100, CURRENT_TIMESTAMP, 100) ON DUPLICATE KEY UPDATE col1 = 1000;
SELECT col1, col2, col3, col5 FROM t4 ORDER BY col5;
--- error: duplicate key update on (x, x, 20)
--- this is because current version is not inplace update but merge,
--- so when the subquery contains multiple same values, it will cause duplicate insert failure.
SELECT col3, sum(col3) * 10 FROM t4 GROUP BY col3 ORDER BY 1, 2;
INSERT INTO t4 (col1, col5)
(SELECT col3, sum(col3) * 10 FROM t4 GROUP BY col3)
ON DUPLICATE KEY UPDATE col1 = 3;
-- test t5 with sequence or default column with volatile function in constaint index
CREATE TABLE t5 (
col1 INT,
col2 INT DEFAULT 1,
col3 BIGSERIAL,
-- col4 TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
col5 INTEGER(10, 5) DEFAULT RANDOM() + 1
) ;
-- test t5 with sequence column in constaint index
CREATE UNIQUE INDEX u_t5_index1 ON t5(col1, col3);
--- should insert
INSERT INTO t5 VALUES (1), (1), (1) ON DUPLICATE KEY UPDATE col2 = col3;
INSERT INTO t5 DEFAULT VALUES ON DUPLICATE KEY UPDATE col2 = col3;
SELECT * FROM t5 ORDER BY col3;
--- should update
INSERT INTO t5 (col1, col3) VALUES (1, 1), (1, 2), (1, 3) ON DUPLICATE KEY UPDATE col5 = col2, col2 = col3 * 10;
SELECT * FROM t5 WHERE col1 = 1 ORDER BY col3;
--- should some insert some update
INSERT INTO t5 (col1, col3) VALUES (2, 5), (2, 6);
SELECT col1, col2, col3 FROM t5 ORDER BY col3;
INSERT INTO t5 (col1) VALUES (2), (2), (2) ON DUPLICATE KEY UPDATE col2 = col3;
SELECT col1, col2, col3 FROM t5 ORDER BY col3;
--- should INSERT and sequence starting from 7
INSERT INTO t5 VALUES (2), (2);
SELECT col1, col2, col3 FROM t5 ORDER BY col3;
-- test with volatile function as default column in constraint index
TRUNCATE t5;
DROP INDEX u_t5_index1;
CREATE UNIQUE INDEX u_t5_index2 ON t5(col1, col5) WHERE col1 > 2;
--- should insert
INSERT INTO t5 VALUES (3), (3), (3) ON DUPLICATE KEY UPDATE col2 = col3;
INSERT INTO t5 (col1) VALUES (4), (4), (4) ON DUPLICATE KEY UPDATE col2 = col3;
SELECT * FROM t5 ORDER BY col3;
--- should update
INSERT INTO t5 (col1, col5) SELECT col1, col5 FROM t5 where col1 = 3 ON DUPLICATE KEY UPDATE col2 = col5 * 100;
SELECT * FROM t5 ORDER BY col3;
--- test subquery
---- should insert
INSERT INTO t5 (col1, col2) SELECT col1, col2 FROM t5 ON DUPLICATE KEY UPDATE col2 = col5 * 100;
SELECT * FROM t5 ORDER BY col3;
---- should update
INSERT INTO t5 SELECT * FROM t5 ON DUPLICATE KEY UPDATE col2 = col5 * 1000;
SELECT * FROM t5 ORDER BY col3;
-- test t6 with one more index
CREATE TABLE t6 (
col1 INT,
col2 INT DEFAULT 1,
col3 BIGSERIAL,
-- col4 TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
col5 INTEGER(10, 5) DEFAULT RANDOM(),
col6 INT,
col7 TEXT
) ;
ALTER TABLE t6 ADD PRIMARY KEY (col1, col3);
CREATE UNIQUE INDEX u_t6_index1 ON t6(col1, col5, col6);
INSERT INTO t6 (col1) VALUES (1), (2), (3), (4), (5);
SELECT col1, col2, col3, col6, col7 FROM t6 ORDER BY col3;
--- should not insert
INSERT INTO t6 (col1) VALUES (1), (2), (3), (4), (5) ON DUPLICATE KEY UPDATE col6 = power(col1, col2);
SELECT col1, col2, col3, col6, col7 FROM t6 ORDER BY col3;
--- should update because primary key matches
INSERT INTO t6 (col1, col3) VALUES (6, 11), (6, 12);
SELECT col1, col2, col3, col6, col7 FROM t6 WHERE col1 = 6 ORDER BY col3;
INSERT INTO t6 (col1) VALUES (6), (6), (6) ON DUPLICATE KEY UPDATE col2 = col1 + col3, col6 = col2 * 10;
SELECT col1, col2, col3, col6, col7 FROM t6 WHERE col1 = 6 ORDER BY col3;
--- should update for those col6 is not null bacause they will match the unique index,
--- and insert for those col6 is null because the unique index containing null never matches,
--- also primary key will not match
--- be ware the sequence column of the inserted row will jump n step, where n is the count of the not null rows,
--- because those sequence have to be generated during the unique index join stage.
INSERT INTO t6 (col1, col5, col6)
(SELECT col1, col5, col6 FROM t6 WHERE col1 = 6)
ON DUPLICATE KEY UPDATE
col7 = col2 + 1;
SELECT col1, col2, col3, col6, col7 FROM t6 WHERE col1 = 6 ORDER BY col1, col3, col6, col7;
--- should update because unique index and primary key both match
INSERT INTO t6 (col1, col3, col5, col6)
(SELECT col1, col3, col5, col6 FROM t6 WHERE col1 = 6 AND col6 IS NOT NULL)
ON DUPLICATE KEY UPDATE
col7 = col7 * 10;
SELECT col1, col2, col3, col6, col7 FROM t6 WHERE col1 = 6 ORDER BY col1, col3, col6, col7;
--- insert when col3 = 17 because constaints does not match,
--- but update when col3 = 18 because 18 has been inserted and will cause a match
INSERT INTO t6 (col1, col3, col5, col6) VALUES (7, 18, 100, 100);
SELECT * FROM t6 WHERE col3 > 16 ORDER BY col1, col3, col6, col7;
INSERT INTO t6 (col1, col5, col6) VALUES (7, 10, 10), (7, 100, 100) ON DUPLICATE KEY UPDATE
col7 = col3 * 100;
SELECT * FROM t6 WHERE col1 = 7 ORDER BY col1, col3, col6, col7;
DROP SCHEMA test_insert_update_003 CASCADE;

View File

@ -0,0 +1,359 @@
--
-- INSERT UPDATE, test explain command, comes from merge_explain and merge_explain_pretty
--
-- initial
CREATE SCHEMA test_insert_update_008;
SET current_schema = test_insert_update_008;
-- enable_upsert_to_merge must is off, or upsert will be translated to merge.
SET enable_upsert_to_merge TO OFF;
CREATE TABLE products_base
(
product_id INTEGER DEFAULT 0,
product_name VARCHAR(60) DEFAULT 'null',
category VARCHAR(60) DEFAULT 'unknown',
total INTEGER DEFAULT '0'
);
INSERT INTO products_base VALUES (1501, 'vivitar 35mm', 'electrncs', 100);
INSERT INTO products_base VALUES (1502, 'olympus is50', 'electrncs', 100);
INSERT INTO products_base VALUES (1600, 'play gym', 'toys', 100);
INSERT INTO products_base VALUES (1601, 'lamaze', 'toys', 100);
INSERT INTO products_base VALUES (1666, 'harry potter', 'dvd', 100);
CREATE TABLE newproducts_base
(
product_id INTEGER DEFAULT 0,
product_name VARCHAR(60) DEFAULT 'null',
category VARCHAR(60) DEFAULT 'unknown',
total INTEGER DEFAULT '0'
);
INSERT INTO newproducts_base VALUES (1502, 'olympus camera', 'electrncs', 200);
INSERT INTO newproducts_base VALUES (1601, 'lamaze', 'toys', 200);
INSERT INTO newproducts_base VALUES (1666, 'harry potter', 'toys', 200);
INSERT INTO newproducts_base VALUES (1700, 'wait interface', 'books', 200);
ANALYZE products_base;
ANALYZE newproducts_base;
--
-- row table
--
CREATE TABLE products_row
(
product_id INTEGER DEFAULT 0 PRIMARY KEY,
product_name VARCHAR(60) DEFAULT 'null',
category VARCHAR(60) DEFAULT 'unknown',
total INTEGER DEFAULT '0'
);
CREATE TABLE newproducts_row
(
product_id INTEGER DEFAULT 0 PRIMARY KEY,
product_name VARCHAR(60) DEFAULT 'null',
category VARCHAR(60) DEFAULT 'unknown',
total INTEGER DEFAULT '0'
);
INSERT INTO products_row SELECT * FROM products_base;
INSERT INTO newproducts_row SELECT * FROM newproducts_base;
ANALYZE products_row;
ANALYZE newproducts_row;
SET explain_perf_mode = normal;
-- explain verbose
EXPLAIN (VERBOSE on, COSTS off)
INSERT INTO products_row
SELECT product_id, product_name, category, total FROM newproducts_row
ON DUPLICATE KEY UPDATE
product_name = excluded.product_name,
category = excluded.category,
total = excluded.total;
EXPLAIN (VERBOSE on, COSTS off)
INSERT INTO products_row
SELECT newproducts_row.product_id,
newproducts_row.product_name,
newproducts_row.category,
newproducts_row.total
FROM newproducts_row, products_row
WHERE products_row.total + newproducts_row.total < 1000
ON DUPLICATE KEY UPDATE
product_name = excluded.product_name,
category = excluded.category,
total = excluded.total;
EXPLAIN (VERBOSE on, COSTS off)
INSERT INTO products_row
SELECT product_id, product_name, category, total
FROM newproducts_row WHERE product_id IS NOT NULL AND product_name IS NOT NULL
ON DUPLICATE KEY UPDATE
product_name = excluded.product_name,
category = excluded.category,
total = excluded.total;
-- explain analyze
BEGIN;
EXPLAIN (ANALYZE on, COSTS off, TIMING off)
INSERT INTO products_row
SELECT product_id, product_name, category, total FROM newproducts_row
ON DUPLICATE KEY UPDATE
product_name = excluded.product_name,
category = excluded.category,
total = excluded.total;
ROLLBACK;
-- explain performance
\o insert_update_explain.txt
BEGIN;
EXPLAIN PERFORMANCE
INSERT INTO products_row
SELECT product_id, product_name, category, total FROM newproducts_row
ON DUPLICATE KEY UPDATE
product_name = excluded.product_name,
category = excluded.category,
total = excluded.total;
ROLLBACK;
\o
-- explain analyze
BEGIN;
EXPLAIN (ANALYZE on, COSTS off, TIMING off)
INSERT INTO products_row
SELECT product_id, product_name, category, total FROM newproducts_row
ON DUPLICATE KEY UPDATE
product_name = excluded.product_name,
category = excluded.category,
total = excluded.total;
ROLLBACK;
-- pretty mode performance
SET explain_perf_mode = pretty;
-- explain verbose
EXPLAIN (VERBOSE on, COSTS off)
INSERT INTO products_row
SELECT product_id, product_name, category, total FROM newproducts_row
ON DUPLICATE KEY UPDATE
product_name = excluded.product_name,
category = excluded.category,
total = excluded.total;
-- explain analyze
BEGIN;
EXPLAIN (ANALYZE on, COSTS off, TIMING off)
INSERT INTO products_row
SELECT product_id, product_name, category, total FROM newproducts_row
ON DUPLICATE KEY UPDATE
product_name = excluded.product_name,
category = excluded.category,
total = excluded.total;
ROLLBACK;
-- explain analyze
BEGIN;
EXPLAIN (ANALYZE on, COSTS off, TIMING off)
INSERT INTO products_row
SELECT product_id, product_name, category, total FROM newproducts_row
ON DUPLICATE KEY UPDATE
product_name = excluded.product_name,
category = excluded.category,
total = excluded.total;
ROLLBACK;
-- explain performance
\o insert_update_explain_pretty.txt
BEGIN;
EXPLAIN PERFORMANCE
INSERT INTO products_row
SELECT product_id, product_name, category, total FROM newproducts_row
ON DUPLICATE KEY UPDATE
product_name = excluded.product_name,
category = excluded.category,
total = excluded.total;
ROLLBACK;
SET explain_perf_mode = run;
BEGIN;
EXPLAIN PERFORMANCE
INSERT INTO products_row
SELECT product_id, product_name, category, total FROM newproducts_row
ON DUPLICATE KEY UPDATE
product_name = excluded.product_name,
category = excluded.category,
total = excluded.total;
ROLLBACK;
SET explain_perf_mode = summary;
BEGIN;
EXPLAIN PERFORMANCE
INSERT INTO products_row
SELECT product_id, product_name, category, total FROM newproducts_row
ON DUPLICATE KEY UPDATE
product_name = excluded.product_name,
category = excluded.category,
total = excluded.total;
ROLLBACK;
\o
CREATE TABLE item
(
a INT DEFAULT 3,
item_id NUMERIC(18,10),
item_name VARCHAR(100),
item_level NUMERIC(39,0),
item_desc VARCHAR(250),
item_subclass_cd VARCHAR(50),
item_type_cd VARCHAR(50),
inventory_ind CHAR(300),
vendor_party_id SMALLINT,
commodity_cd VARCHAR(50),
brand_cd VARCHAR(50),
item_available CHAR(100),
CONSTRAINT u_item_index UNIQUE (item_subclass_cd, vendor_party_id)
)
PARTITION BY RANGE (vendor_party_id)
(
PARTITION item_1 VALUES LESS THAN (0),
PARTITION item_2 VALUES LESS THAN (1),
PARTITION item_3 VALUES LESS THAN (2),
PARTITION item_4 VALUES LESS THAN (3),
PARTITION item_5 VALUES LESS THAN (6),
PARTITION item_6 VALUES LESS THAN (8),
PARTITION item_7 VALUES LESS THAN (10),
PARTITION item_8 VALUES LESS THAN (15),
PARTITION item_9 VALUES LESS THAN (MAXVALUE)
) ENABLE ROW MOVEMENT;
CREATE TABLE region
(
a INT DEFAULT 8,
region_cd VARCHAR(50),
region_name VARCHAR(100),
division_cd VARCHAR(50),
region_mgr_associate_id number(18,9)
);
CREATE TABLE associate_benefit_expense
(
a INT DEFAULT 44,
period_end_dt DATE,
associate_expns_type_cd VARCHAR(50),
associate_party_id INTEGER,
benefit_hours_qty decimal(38,11),
benefit_cost_amt number(38,4)
)
PARTITION BY RANGE (associate_expns_type_cd)
(
PARTITION associate_benefit_expense_1 VALUES LESS THAN ('B'),
PARTITION associate_benefit_expense_2 VALUES LESS THAN ('E'),
PARTITION associate_benefit_expense_3 VALUES LESS THAN ('G'),
PARTITION associate_benefit_expense_4 VALUES LESS THAN ('I'),
PARTITION associate_benefit_expense_5 VALUES LESS THAN ('L'),
PARTITION associate_benefit_expense_6 VALUES LESS THAN ('N'),
PARTITION associate_benefit_expense_7 VALUES LESS THAN ('P'),
PARTITION associate_benefit_expense_8 VALUES LESS THAN ('Q'),
PARTITION associate_benefit_expense_9 VALUES LESS THAN ('R'),
PARTITION associate_benefit_expense_10 VALUES LESS THAN ('T'),
PARTITION associate_benefit_expense_11 VALUES LESS THAN ('U'),
PARTITION associate_benefit_expense_12 VALUES LESS THAN ('V'),
PARTITION associate_benefit_expense_13 VALUES LESS THAN (MAXVALUE)
) ENABLE ROW MOVEMENT;
INSERT INTO item (ITEM_ID, ITEM_NAME, ITEM_DESC, ITEM_SUBCLASS_CD, ITEM_TYPE_CD, INVENTORY_IND, VENDOR_PARTY_ID, COMMODITY_CD, BRAND_CD,ITEM_AVAILABLE) VALUES (0.12, ' ' , 'A' , NULL, 'TGK' , 'A' , 2, 'A' , 'A' , 'Y');
INSERT INTO item (ITEM_ID, ITEM_NAME, ITEM_DESC, ITEM_SUBCLASS_CD, ITEM_TYPE_CD, INVENTORY_IND, VENDOR_PARTY_ID, COMMODITY_CD, BRAND_CD,ITEM_AVAILABLE) VALUES (1.3, 'B' , NULL, 'B' , 'B' , NULL, 1, 'B' , NULL , 'N');
INSERT INTO item (ITEM_ID, ITEM_NAME, ITEM_DESC, ITEM_SUBCLASS_CD, ITEM_TYPE_CD, INVENTORY_IND, VENDOR_PARTY_ID, COMMODITY_CD, BRAND_CD,ITEM_AVAILABLE) VALUES (2.23, 'C' , 'C' , NULL, 'C' , 'C' , 2, 'C' , 'C' , 'N');
INSERT INTO item (ITEM_ID, ITEM_NAME, ITEM_DESC, ITEM_SUBCLASS_CD, ITEM_TYPE_CD, INVENTORY_IND, VENDOR_PARTY_ID, COMMODITY_CD, BRAND_CD,ITEM_AVAILABLE) VALUES (3.33, 'D' , 'D' , 'PT' , NULL, 'D' , 3, 'D' , 'D' , 'N');
INSERT INTO item (ITEM_ID, ITEM_NAME, ITEM_DESC, ITEM_SUBCLASS_CD, ITEM_TYPE_CD, INVENTORY_IND, VENDOR_PARTY_ID, COMMODITY_CD, BRAND_CD,ITEM_AVAILABLE) VALUES (4.98, ' ' , NULL, 'E' , 'E' , 'E' , 4, 'E' , 'E' , 'Y');
INSERT INTO item (ITEM_ID, ITEM_NAME, ITEM_DESC, ITEM_SUBCLASS_CD, ITEM_TYPE_CD, INVENTORY_IND, VENDOR_PARTY_ID, COMMODITY_CD, BRAND_CD,ITEM_AVAILABLE) VALUES (5.01, NULL, 'F' , ' ' , 'F' , 'F' , 5, 'F' , 'F' , 'N');
INSERT INTO item (ITEM_ID, ITEM_NAME, ITEM_DESC, ITEM_SUBCLASS_CD, ITEM_TYPE_CD, INVENTORY_IND, VENDOR_PARTY_ID, COMMODITY_CD, BRAND_CD,ITEM_AVAILABLE) VALUES (6, 'G' , 'G' , 'G' , '_D' , 'G' , 6, 'G' , NULL ,'N');
INSERT INTO item (ITEM_ID, ITEM_NAME, ITEM_DESC, ITEM_SUBCLASS_CD, ITEM_TYPE_CD, INVENTORY_IND, VENDOR_PARTY_ID, COMMODITY_CD, BRAND_CD,ITEM_AVAILABLE) VALUES (0.7, NULL, NULL, NULL, 'H' , 'H' , 7, NULL, 'G' , 'Y');
INSERT INTO item (ITEM_ID, ITEM_NAME, ITEM_DESC, ITEM_SUBCLASS_CD, ITEM_TYPE_CD, INVENTORY_IND, VENDOR_PARTY_ID, COMMODITY_CD, BRAND_CD,ITEM_AVAILABLE) VALUES (0.08, 'I' , ' ' , ' T ' , NULL, 'I' , 8, 'I' , '' , 'N');
INSERT INTO item (ITEM_ID, ITEM_NAME, ITEM_DESC, ITEM_SUBCLASS_CD, ITEM_TYPE_CD, INVENTORY_IND, VENDOR_PARTY_ID, COMMODITY_CD, BRAND_CD,ITEM_AVAILABLE) VALUES (9.12, ' ' , 'J' , ' PP' , 'J' , 'J' , 9, 'J' , NULL , 'Y');
INSERT INTO item (ITEM_ID, ITEM_NAME, ITEM_DESC, ITEM_SUBCLASS_CD, ITEM_TYPE_CD, INVENTORY_IND, VENDOR_PARTY_ID, COMMODITY_CD, BRAND_CD,ITEM_AVAILABLE) VALUES (10.10, NULL, ' ' , 'A' , 'A' , 'A' , 2, NULL, 'A','Y');
--INSERT INTO item (ITEM_ID, ITEM_NAME, ITEM_DESC, ITEM_SUBCLASS_CD, ITEM_TYPE_CD, INVENTORY_IND, VENDOR_PARTY_ID, COMMODITY_CD, BRAND_CD,ITEM_AVAILABLE) VALUES (11.11, 'B' , 'B' , 'B' , 'BCDAA' , NULL, 1, 'B' , 'B','N');
INSERT INTO item (ITEM_ID, ITEM_NAME, ITEM_DESC, ITEM_SUBCLASS_CD, ITEM_TYPE_CD, INVENTORY_IND, VENDOR_PARTY_ID, COMMODITY_CD, BRAND_CD,ITEM_AVAILABLE) VALUES (12.02, 'D' , NULL, NULL, 'C' , 'C' , 2, 'C' , 'C','N');
INSERT INTO item (ITEM_ID, ITEM_NAME, ITEM_DESC, ITEM_SUBCLASS_CD, ITEM_TYPE_CD, INVENTORY_IND, VENDOR_PARTY_ID, COMMODITY_CD, BRAND_CD,ITEM_AVAILABLE) VALUES (13.99, NULL, ' ' , 'D' , 'D' , 'D' , 3, 'D' , 'D','Y');
--INSERT INTO item (ITEM_ID, ITEM_NAME, ITEM_DESC, ITEM_SUBCLASS_CD, ITEM_TYPE_CD, INVENTORY_IND, VENDOR_PARTY_ID, COMMODITY_CD, BRAND_CD,ITEM_AVAILABLE) VALUES (14, 'G' , 'E' , 'E' , NULL, 'E' , 4, 'E' , 'E','N');
INSERT INTO item (ITEM_ID, ITEM_NAME, ITEM_DESC, ITEM_SUBCLASS_CD, ITEM_TYPE_CD, INVENTORY_IND, VENDOR_PARTY_ID, COMMODITY_CD, BRAND_CD,ITEM_AVAILABLE) VALUES (15, 'F' , ' ' , 'C' , 'CLEANING' , 'F' , 5, 'F' , 'F','Y');
INSERT INTO item (ITEM_ID, ITEM_NAME, ITEM_DESC, ITEM_SUBCLASS_CD, ITEM_TYPE_CD, INVENTORY_IND, VENDOR_PARTY_ID, COMMODITY_CD, BRAND_CD,ITEM_AVAILABLE) VALUES (16, '' , 'Z' , NULL, 'G' , 'G' , 6, 'G' , NULL,'N');
INSERT INTO item (ITEM_ID, ITEM_NAME, ITEM_DESC, ITEM_SUBCLASS_CD, ITEM_TYPE_CD, INVENTORY_IND, VENDOR_PARTY_ID, COMMODITY_CD, BRAND_CD,ITEM_AVAILABLE) VALUES (17, NULL, '' , ' PAPER' , 'H' , '' , 7, NULL, NULL,'Y');
INSERT INTO item (ITEM_ID, ITEM_NAME, ITEM_DESC, ITEM_SUBCLASS_CD, ITEM_TYPE_CD, INVENTORY_IND, VENDOR_PARTY_ID, COMMODITY_CD, BRAND_CD,ITEM_AVAILABLE) VALUES (19, ' ' , 'B' , '' , '' , 'I' , 8, 'I' , NULL,'N');
INSERT INTO item (ITEM_ID, ITEM_NAME, ITEM_DESC, ITEM_SUBCLASS_CD, ITEM_TYPE_CD, INVENTORY_IND, VENDOR_PARTY_ID, COMMODITY_CD, BRAND_CD,ITEM_AVAILABLE) VALUES (20 , 'A' , 'J' , 'J' , 'J' , NULL, 9, 'J' , 'G','Y');
/*--REGION--*/
INSERT INTO REGION (REGION_CD, REGION_NAME, DIVISION_CD, REGION_MGR_ASSOCIATE_ID) VALUES ('A', 'A ', 'A', 0.123433);
INSERT INTO REGION (REGION_CD, REGION_NAME, DIVISION_CD, REGION_MGR_ASSOCIATE_ID) VALUES ('B', 'B', 'B', NULL);
INSERT INTO REGION (REGION_CD, REGION_NAME, DIVISION_CD, REGION_MGR_ASSOCIATE_ID) VALUES ('C', 'C', 'C', 2.232008908);
INSERT INTO REGION (REGION_CD, REGION_NAME, DIVISION_CD, REGION_MGR_ASSOCIATE_ID) VALUES ('D', ' DD', 'D', 3.878789);
INSERT INTO REGION (REGION_CD, REGION_NAME, DIVISION_CD, REGION_MGR_ASSOCIATE_ID) VALUES ('E', 'A', 'E', 4.89060603);
INSERT INTO REGION (REGION_CD, REGION_NAME, DIVISION_CD, REGION_MGR_ASSOCIATE_ID) VALUES ('F', 'F', 'F', 5.82703827);
INSERT INTO REGION (REGION_CD, REGION_NAME, DIVISION_CD, REGION_MGR_ASSOCIATE_ID) VALUES ('G', 'G', 'TTT', NULL);
INSERT INTO REGION (REGION_CD, REGION_NAME, DIVISION_CD, REGION_MGR_ASSOCIATE_ID) VALUES ('H', 'H', 'G', 7.3829083);
INSERT INTO REGION (REGION_CD, REGION_NAME, DIVISION_CD, REGION_MGR_ASSOCIATE_ID) VALUES ('I', 'C', 'M', 8.983989);
INSERT INTO REGION (REGION_CD, REGION_NAME, DIVISION_CD, REGION_MGR_ASSOCIATE_ID) VALUES ('J', 'J', 'G', NULL);
INSERT INTO REGION (REGION_CD, REGION_NAME, DIVISION_CD, REGION_MGR_ASSOCIATE_ID) VALUES ('K', ' ', 'C', 2.232008908);
INSERT INTO REGION (REGION_CD, REGION_NAME, DIVISION_CD, REGION_MGR_ASSOCIATE_ID) VALUES ('L', 'D', 'X', 3.878789);
INSERT INTO REGION (REGION_CD, REGION_NAME, DIVISION_CD, REGION_MGR_ASSOCIATE_ID) VALUES ('M', 'TTTTTT ', 'D' , 4.89060603);
INSERT INTO REGION (REGION_CD, REGION_NAME, DIVISION_CD, REGION_MGR_ASSOCIATE_ID) VALUES ('N', 'G' , 'B' , NULL);
INSERT INTO REGION (REGION_CD, REGION_NAME, DIVISION_CD, REGION_MGR_ASSOCIATE_ID) VALUES ('O' , 'G', 'F', 6.6703972);
INSERT INTO ASSOCIATE_BENEFIT_EXPENSE (PERIOD_END_DT, ASSOCIATE_EXPNS_TYPE_CD, ASSOCIATE_PARTY_ID, BENEFIT_HOURS_QTY, BENEFIT_COST_AMT) VALUES (DATE '1970-01-01', 'A', 5, 0.5 , 0.5);
INSERT INTO ASSOCIATE_BENEFIT_EXPENSE (PERIOD_END_DT, ASSOCIATE_EXPNS_TYPE_CD, ASSOCIATE_PARTY_ID, BENEFIT_HOURS_QTY, BENEFIT_COST_AMT) VALUES (DATE '1973-01-01', 'B', 1, NULL, 1.0);
INSERT INTO ASSOCIATE_BENEFIT_EXPENSE (PERIOD_END_DT, ASSOCIATE_EXPNS_TYPE_CD, ASSOCIATE_PARTY_ID, BENEFIT_HOURS_QTY, BENEFIT_COST_AMT) VALUES (DATE '1976-01-01', 'C', 2, 2.0 , NULL);
INSERT INTO ASSOCIATE_BENEFIT_EXPENSE (PERIOD_END_DT, ASSOCIATE_EXPNS_TYPE_CD, ASSOCIATE_PARTY_ID, BENEFIT_HOURS_QTY, BENEFIT_COST_AMT) VALUES (DATE '1979-01-01', 'D', 3, 3.0 , 3.0);
INSERT INTO ASSOCIATE_BENEFIT_EXPENSE (PERIOD_END_DT, ASSOCIATE_EXPNS_TYPE_CD, ASSOCIATE_PARTY_ID, BENEFIT_HOURS_QTY, BENEFIT_COST_AMT) VALUES (DATE '1982-01-01', 'E', 4, 4.0 , 4.0);
INSERT INTO ASSOCIATE_BENEFIT_EXPENSE (PERIOD_END_DT, ASSOCIATE_EXPNS_TYPE_CD, ASSOCIATE_PARTY_ID, BENEFIT_HOURS_QTY, BENEFIT_COST_AMT) VALUES (DATE '1985-01-01', 'F', 5, 5.0 , 5.0);
INSERT INTO ASSOCIATE_BENEFIT_EXPENSE (PERIOD_END_DT, ASSOCIATE_EXPNS_TYPE_CD, ASSOCIATE_PARTY_ID, BENEFIT_HOURS_QTY, BENEFIT_COST_AMT) VALUES (DATE '1988-01-01', 'F', 6, NULL, 6.0);
INSERT INTO ASSOCIATE_BENEFIT_EXPENSE (PERIOD_END_DT, ASSOCIATE_EXPNS_TYPE_CD, ASSOCIATE_PARTY_ID, BENEFIT_HOURS_QTY, BENEFIT_COST_AMT) VALUES (DATE '1991-01-01', 'G', 6, NULL, NULL);
INSERT INTO ASSOCIATE_BENEFIT_EXPENSE (PERIOD_END_DT, ASSOCIATE_EXPNS_TYPE_CD, ASSOCIATE_PARTY_ID, BENEFIT_HOURS_QTY, BENEFIT_COST_AMT) VALUES (DATE '1994-01-01', 'G', 15, 8.0 , 8.0);
INSERT INTO ASSOCIATE_BENEFIT_EXPENSE (PERIOD_END_DT, ASSOCIATE_EXPNS_TYPE_CD, ASSOCIATE_PARTY_ID, BENEFIT_HOURS_QTY, BENEFIT_COST_AMT) VALUES (DATE '1997-01-01', 'G', 16, 9.0 , 9.0);
INSERT INTO ASSOCIATE_BENEFIT_EXPENSE (PERIOD_END_DT, ASSOCIATE_EXPNS_TYPE_CD, ASSOCIATE_PARTY_ID, BENEFIT_HOURS_QTY, BENEFIT_COST_AMT) VALUES (DATE '1983-01-03', 'I', 14, 4.0 , 4.0);
INSERT INTO ASSOCIATE_BENEFIT_EXPENSE (PERIOD_END_DT, ASSOCIATE_EXPNS_TYPE_CD, ASSOCIATE_PARTY_ID, BENEFIT_HOURS_QTY, BENEFIT_COST_AMT) VALUES (DATE '1984-01-01', 'GO', 15, 5.0 , NULL);
INSERT INTO ASSOCIATE_BENEFIT_EXPENSE (PERIOD_END_DT, ASSOCIATE_EXPNS_TYPE_CD, ASSOCIATE_PARTY_ID, BENEFIT_HOURS_QTY, BENEFIT_COST_AMT) VALUES (DATE '1985-05-01', 'I', 16, 6.0 , 6.0);
INSERT INTO ASSOCIATE_BENEFIT_EXPENSE (PERIOD_END_DT, ASSOCIATE_EXPNS_TYPE_CD, ASSOCIATE_PARTY_ID, BENEFIT_HOURS_QTY, BENEFIT_COST_AMT) VALUES (DATE '1990-01-01', 'TTT', 16, NULL, 7.0);
INSERT INTO ASSOCIATE_BENEFIT_EXPENSE (PERIOD_END_DT, ASSOCIATE_EXPNS_TYPE_CD, ASSOCIATE_PARTY_ID, BENEFIT_HOURS_QTY, BENEFIT_COST_AMT) VALUES (DATE '1992-02-01', 'A', 15, 8.0 , 8.0);
INSERT INTO ASSOCIATE_BENEFIT_EXPENSE (PERIOD_END_DT, ASSOCIATE_EXPNS_TYPE_CD, ASSOCIATE_PARTY_ID, BENEFIT_HOURS_QTY, BENEFIT_COST_AMT) VALUES (DATE '1997-02-01', 'G', 17, 9.0 , NULL);
INSERT INTO ASSOCIATE_BENEFIT_EXPENSE (PERIOD_END_DT, ASSOCIATE_EXPNS_TYPE_CD, ASSOCIATE_PARTY_ID, BENEFIT_HOURS_QTY, BENEFIT_COST_AMT) VALUES (DATE '1997-05-01', 'G' , 17, 9.0 , NULL);
ANALYZE item;
ANALYZE region;
ANALYZE associate_benefit_expense;
EXPLAIN (VERBOSE ON, COSTS OFF)
INSERT INTO item (item_level, item_subclass_cd, item_desc, vendor_party_id)
SELECT Table_001.REGION_MGR_ASSOCIATE_ID Column_003,
Table_002.associate_expns_type_cd Column_004,
CAST(Table_001.region_name AS VARCHAR) Column_005,
10 Column_006
-- 'o' Column_007,
-- 'F' Column_008,
-- pg_client_encoding() Column_009
FROM region Table_001, associate_benefit_expense Table_002
ON DUPLICATE KEY UPDATE item_level = -1000;
EXPLAIN (VERBOSE ON, COSTS OFF)
INSERT INTO products_row VALUES(100)
ON DUPLICATE KEY UPDATE total=100;
SET enable_light_proxy=off;
EXPLAIN (VERBOSE ON, COSTS OFF)
INSERT INTO products_row VALUES(100)
ON DUPLICATE KEY UPDATE total=100;
EXPLAIN (VERBOSE ON, COSTS OFF)
INSERT INTO products_row VALUES(100)
ON DUPLICATE KEY UPDATE total=100;
EXPLAIN (VERBOSE ON, COSTS OFF)
INSERT INTO products_row VALUES(100)
ON DUPLICATE KEY UPDATE total=100;
RESET enable_light_proxy;
DROP SCHEMA test_insert_update_008 CASCADE;

View File

@ -0,0 +1,281 @@
DROP SCHEMA test_insert_update_009 CASCADE;
CREATE SCHEMA test_insert_update_009;
SET CURRENT_SCHEMA TO test_insert_update_009;
SET enable_light_proxy=off;
-- enable_upsert_to_merge must is off, or upsert will be translated to merge.
SET enable_upsert_to_merge TO OFF;
-- test t1 with no index
CREATE TABLE t1 (
col1 INT,
col2 INT,
col3 INT DEFAULT 1,
-- col4 TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
col5 BIGSERIAL
) ;
--- distribute key are not allowed to update
INSERT INTO t1 VALUES (1, 2) ON DUPLICATE KEY UPDATE col1 = 3;
--- should always insert
INSERT INTO t1 VALUES (1, 2) ON DUPLICATE KEY UPDATE col2 = 3;
INSERT INTO t1 VALUES (1, 2) ON DUPLICATE KEY UPDATE t1.col2 = 4;
--- appoint column list in insert clause, should always insert
INSERT INTO t1(col1, col3) VALUES (1, 3) ON DUPLICATE KEY UPDATE col2 = 5;
INSERT INTO t1(col1, col3) VALUES (1, 3) ON DUPLICATE KEY UPDATE t1.col2 = 6;
--- multiple rows, should always insert
INSERT INTO t1 VALUES (2, 1), (2, 1) ON DUPLICATE KEY UPDATE col2 = 7, col3 = 7;
SELECT * FROM t1 ORDER BY col5;
--- test union, should insert
INSERT INTO t1 (col1, col2)
SELECT * FROM
(SELECT col1, col2 FROM t1
UNION
SELECT col1, col3 FROM t1) AS union_table
ON DUPLICATE KEY UPDATE col3 = (col1 + col2 + col3);
SELECT col1, col2, col3 FROM t1 WHERE col5 > 6 ORDER BY col1, col2;
--- test subquery, should insert
INSERT INTO t1
(SELECT col1 || col2 || '00' FROM t1 ORDER BY col5)
ON DUPLICATE KEY UPDATE col3 = col1 * 100;
SELECT col1, col2, col3 FROM t1 WHERE col1 >= 100 ORDER BY col1;
-- test t2 with one primary key
CREATE TABLE t2 (
col1 INT,
col2 INT PRIMARY KEY,
col3 INT DEFAULT 1,
col4 TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
col5 BIGSERIAL
) ;
--- distribute key are not allowed to update
INSERT INTO t2 VALUES (1, 1) ON DUPLICATE KEY UPDATE col2 = 3;
INSERT INTO t2 VALUES (1, 1) ON DUPLICATE KEY UPDATE t2.col2 = 3;
INSERT INTO t2 (col2, col3, col4, col5)
VALUES (10, 10, CURRENT_TIMESTAMP(0), 10),
(20, 20, CURRENT_TIMESTAMP(1), 20),
(30, 30, CURRENT_TIMESTAMP(2), 30)
ON DUPLICATE KEY UPDATE
col1 = 100,
col2 = 100,
col3 = 100,
col4 = '2019-08-09'::TIMESTAMP,
col5 = 100;
--- should insert
INSERT INTO t2 VALUES (1, 1) ON DUPLICATE KEY UPDATE col1 = 30;
INSERT INTO t2 VALUES (2, 2) ON DUPLICATE KEY UPDATE t2.col1 = 40;
INSERT INTO t2 VALUES (3, 3) ON DUPLICATE KEY UPDATE col1 = col1 * 2;
INSERT INTO t2 VALUES (4, 4) ON DUPLICATE KEY UPDATE t2.col1 = t2.col1 * 2 ;
INSERT INTO t2 VALUES (5, 5) ON DUPLICATE KEY UPDATE col1 = col2 + 1;
INSERT INTO t2 VALUES (6, 6) ON DUPLICATE KEY UPDATE t2.col1 = t2.col2 + 1;
INSERT INTO t2 VALUES (7, 7) ON DUPLICATE KEY UPDATE col1 = extract(dow from col4) + 10;
INSERT INTO t2 VALUES (8, 8) ON DUPLICATE KEY UPDATE t2.col1 = extract(century from col4) * 100 + extract(isodow from col4);
SELECT col1, col2, col3, col5 FROM t2 ORDER BY col5;
--- should update
INSERT INTO t2 VALUES (3, 1) ON DUPLICATE KEY UPDATE col1 = 30, col3 = col5 + 1;
INSERT INTO t2 VALUES (4, 2) ON DUPLICATE KEY UPDATE t2.col1 = 40, t2.col3 = t2.col5;
INSERT INTO t2 VALUES (3, 3), (4, 4) ON DUPLICATE KEY UPDATE col3 = t2.col5 + 1;
INSERT INTO t2 VALUES (5, 5) ON DUPLICATE KEY UPDATE col1 = extract(dow from col4) + 10;
INSERT INTO t2 VALUES (6, 6) ON DUPLICATE KEY UPDATE t2.col1 = extract(century from col4) * 100 + extract(isodow from col4);
SELECT col1, col2, col3, col5 FROM t2 ORDER BY col5;
-- primary key are not allowed to be null
INSERT INTO t2 (col1) VALUES (10) ON DUPLICATE KEY UPDATE col1 = 10;
--- appoint column list in insert clause
---- should insert
INSERT INTO t2 (col2, col3) VALUES (9, 9) ON DUPLICATE KEY UPDATE col1 = 90;
INSERT INTO t2 (col2, col3, col4, col5)
VALUES (10, 10, CURRENT_TIMESTAMP(0), 10),
(20, 20, CURRENT_TIMESTAMP(1), 20),
(30, 30, CURRENT_TIMESTAMP(2), 30)
ON DUPLICATE KEY UPDATE
col1 = 100,
col3 = 100,
col4 = '2019-08-20'::TIMESTAMP,
col5 = 100;
SELECT * FROM t2 ORDER BY col5;
---- should update
INSERT INTO t2 (col2, col3) VALUES (9, 9) ON DUPLICATE KEY UPDATE col1 = 90;
INSERT INTO t2 (col2, col3, col4, col5)
VALUES (10, 10, CURRENT_TIMESTAMP(0), 10),
(20, 20, CURRENT_TIMESTAMP(1), 20),
(30, 30, CURRENT_TIMESTAMP(2), 30)
ON DUPLICATE KEY UPDATE
col1 = 100,
col3 = 100,
col4 = '2019-08-20'::TIMESTAMP,
col5 = 100;
SELECT * FROM t2 ORDER BY col5, col2;
--- test subquery
---- should insert
INSERT INTO t2
(SELECT col1 * 1000, col2 * 1000 + 1 FROM t2 ORDER BY col5 LIMIT 2)
ON DUPLICATE KEY UPDATE col3 = col2 + 1;
INSERT INTO t2 (col2, col3)
(SELECT col1 * 1000 + 2, col2 * 1000 FROM t2 ORDER BY col5 LIMIT 2 OFFSET 1)
ON DUPLICATE KEY UPDATE col3 = col2 + 1;
SELECT col1, col2, col3, col5 FROM t2 ORDER BY col5, col2;
---- should update
INSERT INTO t2
(SELECT col1 * 1000, col2 * 1000 + 1 FROM t2 ORDER BY col5 LIMIT 2)
ON DUPLICATE KEY UPDATE col3 = col2 + 1;
INSERT INTO t2 (col2, col3)
(SELECT col1 * 1000 + 2, col2 * 1000 FROM t2 ORDER BY col5 LIMIT 2 OFFSET 1)
ON DUPLICATE KEY UPDATE col3 = col2 + 1;
SELECT col1, col2, col3, col5 FROM t2 ORDER BY col5, col2;
--- test union, some insert some update
SELECT col1, col2 FROM t1 WHERE col2 IS NOT NULL
UNION
SELECT col1, col3 FROM t1 ORDER BY 1, 2;
INSERT INTO t2 (col1, col2)
SELECT * FROM
(SELECT col1, col2 FROM t1 WHERE col2 IS NOT NULL
UNION
SELECT col1, col3 FROM t1) AS union_table
ON DUPLICATE KEY UPDATE col3 = (col1 + col2 + col3);
SELECT col1, col2, col3, col5 FROM t2 ORDER BY col5, col2;
INSERT INTO t2 (col1, col2)
SELECT col1, col2 FROM t1 WHERE col2 IS NOT NULL
UNION
SELECT col1, col3 FROM t1
ON DUPLICATE KEY UPDATE col3 = (col1 + col2 + col3);
SELECT col1, col2, col3, col5 FROM t2 ORDER BY col5, col2;
reset behavior_compat_options;
-- test INTERSECT, should update
(SELECT col1, col1 + col2 FROM t1 WHERE col2 IS NOT NULL
UNION
SELECT 1, 2)
INTERSECT
SELECT col1, col3 FROM t1;
INSERT INTO t2 (col1, col2)
(SELECT col1, col1 + col2 FROM t1 WHERE col2 IS NOT NULL
UNION
SELECT 1, 2)
INTERSECT
SELECT col1, col3 FROM t1
ON DUPLICATE KEY UPDATE col3 = (col1 + col2 + col3);
SELECT col1, col2, col3, col5 FROM t2 WHERE col2 = 3 ORDER BY col5, col2;
-- test EXCEPT, should update
SELECT col1, col2 FROM t1 WHERE col2 IS NOT NULL
EXCEPT
(SELECT col1, col3 FROM t1
UNION
SELECT NULL, NULL);
INSERT INTO t2 (col1, col2)
SELECT col1, col2 FROM t1 WHERE col2 IS NOT NULL
EXCEPT
(SELECT col1, col3 FROM t1
UNION
SELECT NULL, NULL)
ON DUPLICATE KEY UPDATE col3 = (col1 + col2 + col3);
SELECT col1, col2, col3, col5 FROM t2 WHERE col2 = 2 ORDER BY col5, col2;
-- test unique index with not default value
ALTER TABLE t2 DROP CONSTRAINT t2_pkey;
CREATE UNIQUE INDEX t2_u_index ON t2(col2, col5);
SELECT col1, col2 FROM t1 WHERE col2 IS NOT NULL
EXCEPT
(SELECT col1, col3 FROM t1
UNION
SELECT NULL, NULL);
INSERT INTO t2
SELECT col1, col2 FROM t1 WHERE col2 IS NOT NULL
EXCEPT
(SELECT col1, col3 FROM t1
UNION
SELECT NULL, NULL)
ON DUPLICATE KEY UPDATE col3 = (col1 + col2 + col3);
SELECT col1, col2, col3, col5 FROM t2 WHERE col2 = 2 ORDER BY col5, col2;
-- test t3 with one primary index with two columns
CREATE TABLE t3 (
col1 INT,
col2 INT,
col3 INT DEFAULT 1,
-- col4 TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
col5 BIGSERIAL,
PRIMARY KEY (col2, col3)
) ;
--- column referenced by primary key are not allowed to update
INSERT INTO t3 VALUES (1, 1) ON DUPLICATE KEY UPDATE col3 = 3;
--- should insert when not contains primary key and not all primary key referred columns have default value.
--- but will fail cause primary key should not be null
INSERT INTO t3 (col1) VALUES (1) ON DUPLICATE KEY UPDATE col1 = 2;
--- should insert
--- (SEQUENCE BUG: the serial column will starts from 2 since the above statement has applied for a sequence)
INSERT INTO t3 VALUES (1, 1) ON DUPLICATE KEY UPDATE col1 = 10;
INSERT INTO t3 VALUES (2, 2, 2) ON DUPLICATE KEY UPDATE col5 = 20;
SELECT * FROM t3 order by col5;
--- should update
INSERT INTO t3 VALUES (1, 1) ON DUPLICATE KEY UPDATE col1 = 10;
INSERT INTO t3 VALUES (2, 2, 2) ON DUPLICATE KEY UPDATE col5 = 20;
SELECT * FROM t3 order by col5;
--- test subquery
---- should insert
INSERT INTO t3 (col2, col3) (SELECT max(col2) + 1, max(col3) + 1 FROM t3) ON DUPLICATE KEY UPDATE col1 = col2 + col3;
SELECT * FROM t3 order by col5;
---- should update
INSERT INTO t3 (col2, col3) (SELECT max(col2), max(col3) FROM t3) ON DUPLICATE KEY UPDATE col1 = col2 + col3;
SELECT * FROM t3 order by col5;
-- test t3 with one unique index with two columns
TRUNCATE t3;
ALTER TABLE t3 DROP CONSTRAINT t3_pkey;
ALTER TABLE t3 ALTER COLUMN col2 DROP NOT NULL;
CREATE UNIQUE INDEX t3_ukey ON t3 (col2, col3);
--- column referenced by unique key are not allowed to update
INSERT INTO t3 VALUES (1, 1) ON DUPLICATE KEY UPDATE col3 = 3;
--- should insert cause not contains unique key and not all unique key referred columns have default value.
INSERT INTO t3 (col1) VALUES (1) ON DUPLICATE KEY UPDATE col1 = 2;
INSERT INTO t3 (col1) VALUES (1) ON DUPLICATE KEY UPDATE col1 = 2;
SELECT * FROM t3 order by col5;
--- should insert
INSERT INTO t3 VALUES (1, 1) ON DUPLICATE KEY UPDATE col1 = 10;
INSERT INTO t3 VALUES (2, 2, 2) ON DUPLICATE KEY UPDATE t3.col5 = 20;
SELECT * FROM t3 ORDER BY col5;
--- should update
INSERT INTO t3 VALUES (1, 1) ON DUPLICATE KEY UPDATE t3.col1 = 10;
INSERT INTO t3 VALUES (2, 2, 2) ON DUPLICATE KEY UPDATE col5 = 20;
SELECT * FROM t3 ORDER BY col5;
--- test subquery
---- should insert
INSERT INTO t3 (SELECT 100, NULL, max(col3) FROM t3) ON DUPLICATE KEY UPDATE col1 = col2 + col3;
INSERT INTO t3 (SELECT 100, NULL, max(col3) FROM t3) ON DUPLICATE KEY UPDATE col1 = col2 + col3;
INSERT INTO t3 (col2, col3) (SELECT max(col2) + 1, max(col3) + 1 FROM t3) ON DUPLICATE KEY UPDATE col1 = col2 + col3;
SELECT * FROM t3 ORDER BY col5;
---- should update
INSERT INTO t3 (col2, col3) (SELECT max(col2), max(col3) FROM t3) ON DUPLICATE KEY UPDATE col1 = col2 + col3;
SELECT * FROM t3 ORDER BY col5;
RESET enable_light_proxy;
DROP SCHEMA test_insert_update_009 CASCADE;

View File

@ -0,0 +1,144 @@
DROP SCHEMA test_insert_update_010 CASCADE;
CREATE SCHEMA test_insert_update_010;
SET CURRENT_SCHEMA TO test_insert_update_010;
-- enable_upsert_to_merge must is off, or upsert will be translated to merge.
SET enable_upsert_to_merge TO OFF;
-- test t4 with one primary key with three columns
CREATE TABLE t4 (
col1 INT,
col2 INT DEFAULT 0,
col3 INT DEFAULT 1,
col4 TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
col5 BIGSERIAL,
PRIMARY KEY (col2, col3, col5)
) ;
--- should insert
INSERT INTO t4 VALUES (1) ON DUPLICATE KEY UPDATE col1 = 10;
INSERT INTO t4 VALUES (1) ON DUPLICATE KEY UPDATE col1 = 10;
INSERT INTO t4 VALUES (2, 2, 2) ON DUPLICATE KEY UPDATE col1 = 200;
INSERT INTO t4 VALUES (100, 100, 100, CURRENT_TIMESTAMP, 100) ON DUPLICATE KEY UPDATE col1 = 1000;
SELECT col1, col2, col3, col5 FROM t4 ORDER BY col5;
--- should update
INSERT INTO t4 VALUES (2, 2, 2, CURRENT_TIMESTAMP, 3) ON DUPLICATE KEY UPDATE col1 = 200;
INSERT INTO t4 VALUES (100, 100, 100, CURRENT_TIMESTAMP, 100) ON DUPLICATE KEY UPDATE col1 = 1000;
SELECT col1, col2, col3, col5 FROM t4 ORDER BY col5;
--- error: duplicate key update on (x, x, 20)
--- this is because current version is not inplace update but merge,
--- so when the subquery contains multiple same values, it will cause duplicate insert failure.
SELECT col3, sum(col3) * 10 FROM t4 GROUP BY col3 ORDER BY 1, 2;
INSERT INTO t4 (col1, col5)
(SELECT col3, sum(col3) * 10 FROM t4 GROUP BY col3)
ON DUPLICATE KEY UPDATE col1 = 3;
-- test t5 with sequence or default column with volatile function in constaint index
CREATE TABLE t5 (
col1 INT,
col2 INT DEFAULT 1,
col3 BIGSERIAL,
-- col4 TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
col5 INTEGER(10, 5) DEFAULT RANDOM() + 1
) ;
-- test t5 with sequence column in constaint index
CREATE UNIQUE INDEX u_t5_index1 ON t5(col1, col3);
--- should insert
INSERT INTO t5 VALUES (1), (1), (1) ON DUPLICATE KEY UPDATE col2 = col3;
INSERT INTO t5 DEFAULT VALUES ON DUPLICATE KEY UPDATE col2 = col3;
SELECT * FROM t5 ORDER BY col3;
--- should update
INSERT INTO t5 (col1, col3) VALUES (1, 1), (1, 2), (1, 3) ON DUPLICATE KEY UPDATE col5 = col2, col2 = col3 * 10;
SELECT * FROM t5 WHERE col1 = 1 ORDER BY col3;
--- should some insert some update
INSERT INTO t5 (col1, col3) VALUES (2, 5), (2, 6);
SELECT col1, col2, col3 FROM t5 ORDER BY col3;
INSERT INTO t5 (col1) VALUES (2), (2), (2) ON DUPLICATE KEY UPDATE col2 = col3;
SELECT col1, col2, col3 FROM t5 ORDER BY col3;
--- should INSERT and sequence starting from 7
INSERT INTO t5 VALUES (2), (2);
SELECT col1, col2, col3 FROM t5 ORDER BY col3;
-- test with volatile function as default column in constraint index
TRUNCATE t5;
DROP INDEX u_t5_index1;
CREATE UNIQUE INDEX u_t5_index2 ON t5(col1, col5) WHERE col1 > 2;
--- should insert
INSERT INTO t5 VALUES (3), (3), (3) ON DUPLICATE KEY UPDATE col2 = col3;
INSERT INTO t5 (col1) VALUES (4), (4), (4) ON DUPLICATE KEY UPDATE col2 = col3;
SELECT * FROM t5 ORDER BY col3;
--- should update
INSERT INTO t5 (col1, col5) SELECT col1, col5 FROM t5 where col1 = 3 ON DUPLICATE KEY UPDATE col2 = col5 * 100;
SELECT * FROM t5 ORDER BY col3;
--- test subquery
---- should insert
INSERT INTO t5 (col1, col2) SELECT col1, col2 FROM t5 ON DUPLICATE KEY UPDATE col2 = col5 * 100;
SELECT * FROM t5 ORDER BY col3;
---- should update
INSERT INTO t5 SELECT * FROM t5 ON DUPLICATE KEY UPDATE col2 = col5 * 1000;
SELECT * FROM t5 ORDER BY col3;
-- test t6 with one more index
CREATE TABLE t6 (
col1 INT,
col2 INT DEFAULT 1,
col3 BIGSERIAL,
-- col4 TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
col5 INTEGER(10, 5) DEFAULT RANDOM(),
col6 INT,
col7 TEXT
) ;
ALTER TABLE t6 ADD PRIMARY KEY (col1, col3);
CREATE UNIQUE INDEX u_t6_index1 ON t6(col1, col5, col6);
INSERT INTO t6 (col1) VALUES (1), (2), (3), (4), (5);
SELECT col1, col2, col3, col6, col7 FROM t6 ORDER BY col3;
--- should insert
INSERT INTO t6 (col1) VALUES (1), (2), (3), (4), (5) ON DUPLICATE KEY UPDATE col6 = power(col1, col2);
SELECT col1, col2, col3, col6, col7 FROM t6 ORDER BY col3;
--- should update because primary key matches
INSERT INTO t6 (col1, col3) VALUES (6, 11), (6, 12);
SELECT col1, col2, col3, col6, col7 FROM t6 WHERE col1 = 6 ORDER BY col3;
INSERT INTO t6 (col1) VALUES (6), (6), (6) ON DUPLICATE KEY UPDATE col2 = col1 + col3, col6 = col2 * 10;
SELECT col1, col2, col3, col6, col7 FROM t6 WHERE col1 = 6 ORDER BY col3;
--- should update for those col6 is not null bacause they will match the unique index,
--- and insert for those col6 is null because the unique index containing null never matches,
--- also primary key will not match
--- be ware the sequence column of the inserted row will jump n step, where n is the count of the not null rows,
--- because those sequence have to be generated during the unique index join stage.
INSERT INTO t6 (col1, col5, col6)
(SELECT col1, col5, col6 FROM t6 WHERE col1 = 6)
ON DUPLICATE KEY UPDATE
col7 = col2 + 1;
SELECT col1, col2, col3, col6, col7 FROM t6 WHERE col1 = 6 ORDER BY col1, col3, col6, col7;
--- should update because unique index and primary key both match
INSERT INTO t6 (col1, col3, col5, col6)
(SELECT col1, col3, col5, col6 FROM t6 WHERE col1 = 6 AND col6 IS NOT NULL)
ON DUPLICATE KEY UPDATE
col7 = col7 * 10;
SELECT col1, col2, col3, col6, col7 FROM t6 WHERE col1 = 6 ORDER BY col1, col3, col6, col7;
--- insert when col3 = 17 because constaints does not match,
--- but update when col3 = 18 because 18 has been inserted and will cause a match
INSERT INTO t6 (col1, col3, col5, col6) VALUES (7, 18, 100, 100);
SELECT * FROM t6 WHERE col3 > 16 ORDER BY col1, col3, col6, col7;
INSERT INTO t6 (col1, col5, col6) VALUES (7, 10, 10), (7, 100, 100) ON DUPLICATE KEY UPDATE
col7 = col3 * 100;
SELECT * FROM t6 WHERE col1 = 7 ORDER BY col1, col3, col6, col7;
DROP SCHEMA test_insert_update_010 CASCADE;

View File

@ -0,0 +1,3 @@
\c upsert
DROP SCHEMA upsert_test CASCADE;
DROP SCHEMA upsert_test_unlog CASCADE;

View File

@ -0,0 +1,146 @@
--------------------------------------------------------------------------------------------
/*
* procedure
*/
--------------------------------------------------------------------------------------------
\c upsert;
SET CURRENT_SCHEMA TO upsert_test_procedure;
-- enable_upsert_to_merge must be off, or upsert will be translated to merge.
SET enable_upsert_to_merge TO OFF;
SHOW enable_upsert_to_merge;
drop table IF EXISTS t_proc;
create table t_proc(c1 int, c2 int, c3 int unique);
insert into t_proc select a,a,a from generate_series(1,20) as a;
select *from t_proc order by c3;
create or replace procedure mul_ups( c in INTEGER)
as
declare
val int;
begin
for val in select c3 from t_proc loop
insert into t_proc values(c,c, val) on duplicate key update c1 = c, c2 =c;
end loop;
end;
/
call mul_ups(100);
select *from t_proc order by c3;
create or replace procedure mul_ups( c in INTEGER)
as
declare
val int;
begin
for val in select c3 from t_proc loop
insert into t_proc values(c,c, val) on duplicate key update c1 = $1, c2 =$1;
end loop;
end;
/
call mul_ups(200);
select *from t_proc order by c3;
create or replace procedure mul_ups_00()
as
declare
val int;
begin
for val in select c3 from t_proc loop
insert into t_proc values(val,val,val) on duplicate key update c1 = 300, c2 =300;
end loop;
end;
/
call mul_ups_00();
select *from t_proc order by c3;
declare
val int;
c int :=400;
begin
for val in select c3 from t_proc loop
insert into t_proc values(c,c, val) on duplicate key update c1 = c, c2 =c;
end loop;
end;
/
select *from t_proc order by c3;
create or replace procedure mul_ups( c in INTEGER)
as
declare
val int;
begin
for val in select c3 from t_proc loop
insert into t_proc values(c,c, val+100) on duplicate key update c1 = $1, c2 =$1;
end loop;
end;
/
call mul_ups(500);
select *from t_proc order by c3;
/*
* insert
*/
drop table if exists t_default;
CREATE TABLE t_default (c1 INT PRIMARY KEY DEFAULT 10, c2 FLOAT DEFAULT 3.0, c3 TIMESTAMP DEFAULT '20200508');
create view v_default as select *from t_default order by c1;
-- insert src
---- insert values
truncate t_default;
insert into t_default values(DEFAULT, DEFAULT, DEFAULT);
insert into t_default values(1, 2, '20200630');
select *from t_default order by c1;
insert into t_default values(DEFAULT, DEFAULT, DEFAULT) on duplicate key update c2 = 1;
select *from t_default order by c1;
insert into t_default values(1, 2, '20200630') on duplicate key update c2 = 2;
select *from t_default order by c1;
insert into t_default values(DEFAULT, DEFAULT, DEFAULT),(1, 2, '20200630') on duplicate key update c2 = 3;
select *from t_default order by c1;
---- insert subquery
insert into t_default select *from t_default order by c1 on duplicate key update c2 = 4;
select *from t_default order by c1;
insert into t_default select *from t_default order by c1 limit 1 on duplicate key update c2 = 5;
select *from t_default order by c1;
insert into t_default select *from t_default where c1=10 on duplicate key update c2 = 6;
select *from t_default order by c1;
insert into t_default select *from t_default order by c1 on duplicate key update c2 = 7;
select *from t_default order by c1;
insert into t_default select *from v_default order by c1 on duplicate key update c2 = 8;
select *from t_default order by c1;
insert into t_default select *from t_default union select c1+1,c2+1,c3+1 from t_default order by c1 on duplicate key update c2 = 9;
select *from t_default order by c1;
insert into t_default(c1,c2) select max(c1),c2 from t_default group by c2 on duplicate key update c2 = 10;
-- index
---- mul index
truncate t_default;
create unique index t_default_mul on t_default(c1,c3);
insert into t_default values(DEFAULT, DEFAULT, DEFAULT);
insert into t_default values(1, 2, '20200630');
select *from t_default order by c1;
insert into t_default values(DEFAULT, DEFAULT, DEFAULT) on duplicate key update c2 = 1;
select *from t_default order by c1;
insert into t_default values(1, 2, '20200630') on duplicate key update c2 = 2;
select *from t_default order by c1;
insert into t_default values(DEFAULT, DEFAULT, DEFAULT),(1, 2, '20200630') on duplicate key update c2 = 3;
select *from t_default order by c1;
insert into t_default select *from t_default on duplicate key update c2 = 4;
select *from t_default order by c1;

View File

@ -0,0 +1,63 @@
--------------------------------------------------------------------------------------------
/*
* explain upsert
*/
--------------------------------------------------------------------------------------------
\c upsert;
SET CURRENT_SCHEMA TO upsert_test_explain;
-- enable_upsert_to_merge must be off, or upsert will be translated to merge.
SET enable_upsert_to_merge TO OFF;
SHOW enable_upsert_to_merge;
create temp table up_expl_temp(c1 int, c2 int, c3 int unique) ;
insert into up_expl_hash select a,a,a from generate_series(1,20) as a;
insert into up_expl_repl select a,a,a from generate_series(1,20) as a;
insert into up_expl_part select a,a,a from generate_series(1,20) as a;
insert into up_expl_temp select a,a,a from generate_series(1,20) as a;
insert into up_expl_unlog select a,a,a from generate_series(1,20) as a;
insert into up_expl_node select a,a,a from generate_series(1,20) as a;
insert into up_expl_repl2 select a,a,a,a,a from generate_series(1,20) as a;
EXPLAIN (VERBOSE on, COSTS off, TIMING off) insert into up_expl_hash values(1,1,1) on duplicate key update c1 = 2;
EXPLAIN (ANALYZE on, COSTS off, TIMING off) insert into up_expl_hash values(1,1,1) on duplicate key update c1 = 2;
EXPLAIN PERFORMANCE insert into up_expl_hash values(1,1,1) on duplicate key update c1 = 2;
EXPLAIN (VERBOSE on, COSTS off, TIMING off) insert into up_expl_hash values(1,1,1),(2,2,2)on duplicate key update c1 = 2;
EXPLAIN (ANALYZE on, COSTS off, TIMING off) insert into up_expl_hash values(1,1,1),(2,2,2)on duplicate key update c1 = 2;
EXPLAIN (VERBOSE on, COSTS off, TIMING off) insert into up_expl_repl values(1,1,1) on duplicate key update c1 = 2;
EXPLAIN (ANALYZE on, COSTS off, TIMING off) insert into up_expl_repl values(1,1,1) on duplicate key update c1 = 2;
EXPLAIN (VERBOSE on, COSTS off, TIMING off) insert into up_expl_part values(1,1,1) on duplicate key update c1 = 2;
EXPLAIN (ANALYZE on, COSTS off, TIMING off) insert into up_expl_part values(1,1,1) on duplicate key update c1 = 2;
EXPLAIN (VERBOSE on, COSTS off, TIMING off) insert into up_expl_temp values(1,1,1) on duplicate key update c1 = 2;
EXPLAIN (ANALYZE on, COSTS off, TIMING off) insert into up_expl_temp values(1,1,1) on duplicate key update c1 = 2;
EXPLAIN (VERBOSE on, COSTS off, TIMING off) insert into up_expl_unlog values(1,1,1) on duplicate key update c1 = 2;
EXPLAIN (ANALYZE on, COSTS off, TIMING off) insert into up_expl_unlog values(1,1,1) on duplicate key update c1 = 2;
EXPLAIN (VERBOSE on, COSTS off, TIMING off) insert into up_expl_node values(1,1,1) on duplicate key update c1 = 2;
EXPLAIN (ANALYZE on, COSTS off, TIMING off) insert into up_expl_node values(1,1,1) on duplicate key update c1 = 2;
EXPLAIN (VERBOSE on, COSTS off, TIMING off) insert into up_expl_hash values(1,1,1),(2,2,2)on duplicate key update nothing;
EXPLAIN (ANALYZE on, COSTS off, TIMING off) insert into up_expl_hash values(1,1,1),(2,2,2)on duplicate key update nothing;
EXPLAIN (VERBOSE on, COSTS off, TIMING off) insert into up_expl_repl values(1,1,1) on duplicate key update nothing;
EXPLAIN (ANALYZE on, COSTS off, TIMING off) insert into up_expl_repl values(1,1,1) on duplicate key update nothing;
EXPLAIN (VERBOSE on, COSTS off, TIMING off) insert into up_expl_part values(1,1,1) on duplicate key update nothing;
EXPLAIN (ANALYZE on, COSTS off, TIMING off) insert into up_expl_part values(1,1,1) on duplicate key update nothing;
EXPLAIN (VERBOSE on, COSTS off, TIMING off) insert into up_expl_temp values(1,1,1) on duplicate key update nothing;
EXPLAIN (ANALYZE on, COSTS off, TIMING off) insert into up_expl_temp values(1,1,1) on duplicate key update nothing;
EXPLAIN (VERBOSE on, COSTS off, TIMING off) insert into up_expl_unlog values(1,1,1) on duplicate key update nothing;
EXPLAIN (ANALYZE on, COSTS off, TIMING off) insert into up_expl_unlog values(1,1,1) on duplicate key update nothing;
EXPLAIN (VERBOSE on, COSTS off, TIMING off) insert into up_expl_node values(1,1,1) on duplicate key update nothing;
EXPLAIN (ANALYZE on, COSTS off, TIMING off) insert into up_expl_node values(1,1,1) on duplicate key update nothing;

View File

@ -0,0 +1,113 @@
\c upsert
SET CURRENT_SCHEMA TO upsert_test;
-- enable_upsert_to_merge must be off, or upsert will be translated to merge.
SET enable_upsert_to_merge TO OFF;
SHOW enable_upsert_to_merge;
-- support multiple set
INSERT INTO t_grammer VALUES(11, 1) ON DUPLICATE KEY UPDATE c2 = 2, c4 = ROW(10, 20), c3 = '{10, 20, 30}';
INSERT INTO t_grammer VALUES(12, 2) ON DUPLICATE KEY UPDATE c2 = 2, c3[1] = 3;
-- support const value and expr
INSERT INTO t_grammer VALUES(23) ON DUPLICATE KEY UPDATE c2 = 2;
INSERT INTO t_grammer VALUES(24) ON DUPLICATE KEY UPDATE c2 = length('test') + 100;
-- support without table name
INSERT INTO t_grammer VALUES(31, 1) ON DUPLICATE KEY UPDATE c2 = c1, c4.a = VALUES(c1);
INSERT INTO t_grammer VALUES(32, 2) ON DUPLICATE KEY UPDATE c2 = c1 + 5, c4.a = VALUES(c1);
-- support with table name
INSERT INTO t_grammer VALUES(41, 1) ON DUPLICATE KEY UPDATE c2 = t_grammer.c1, c4.a = VALUES(c1);
INSERT INTO t_grammer VALUES(42, 2) ON DUPLICATE KEY UPDATE c2 = t_grammer.c1 + 5, c4.a = VALUES(c1);
-- support EXCLUDED alone and with expr
INSERT INTO t_grammer VALUES(51, 1) ON DUPLICATE KEY UPDATE c2 = c1 + 5, c4.a = EXCLUDED.c1;
INSERT INTO t_grammer VALUES(52, 2) ON DUPLICATE KEY UPDATE c2 = t_grammer.c1 + 5, c4.a = EXCLUDED.c1 + 5;
INSERT INTO t_grammer VALUES(53, 3) ON DUPLICATE KEY UPDATE c4.a = sqrt(EXCLUDED.c1 - EXCLUDED.c2 - 1) + 1, c2 = t_grammer.c1 + 5;
INSERT INTO t_grammer VALUES(54, 4) ON DUPLICATE KEY UPDATE c4.b = EXCLUDED.c1 + t_grammer.c1;
INSERT INTO t_grammer VALUES(55, 5) ON DUPLICATE KEY UPDATE c4.a = EXCLUDED.c2, c4.b = EXCLUDED.c1 + sqrt(c1 - 6);
-- support ARRAY
INSERT INTO t_grammer VALUES(61, 1) ON DUPLICATE KEY UPDATE c2 = VALUES(c3[1]);
INSERT INTO t_grammer VALUES(62, 2) ON DUPLICATE KEY UPDATE c5 = VALUES(c3[2,3]);
INSERT INTO t_grammer VALUES(63, 3) ON DUPLICATE KEY UPDATE c5 = VALUES(c3[2:3]);
INSERT INTO t_grammer VALUES(64, 4, '{10, 20, 30}') ON DUPLICATE KEY UPDATE c2 = EXCLUDED.c3[1];
INSERT INTO t_grammer VALUES(65, 5, '{10, 20, 30}') ON DUPLICATE KEY UPDATE c5 = EXCLUDED.c3[2,3];
INSERT INTO t_grammer VALUES(66, 6, '{10, 20, 30}') ON DUPLICATE KEY UPDATE c5 = EXCLUDED.c3[1:2];
INSERT INTO t_grammer VALUES(67, 7, '{10, 20, 30}') ON DUPLICATE KEY UPDATE c2 = c3[1];
INSERT INTO t_grammer VALUES(68, 8, '{10, 20, 30}') ON DUPLICATE KEY UPDATE c5 = c3[2,3];
INSERT INTO t_grammer VALUES(69, 9, '{10, 20, 30}') ON DUPLICATE KEY UPDATE c5 = c3[1:2];
-- support user defined type
INSERT INTO t_grammer VALUES(71, 1) ON DUPLICATE KEY UPDATE c4.a = c3[1] + c1;
INSERT INTO t_grammer VALUES(72, 2, '{71, 72, 73}') ON DUPLICATE KEY UPDATE c4.a = c3[1] + c1;
INSERT INTO t_grammer VALUES(73, 3, '{71, 72, 73}') ON DUPLICATE KEY UPDATE c4.a = c3[1] + c1, c4.b = c3[2];
INSERT INTO t_grammer VALUES(74, 4, '{71, 72, 73}', ROW(74, 75)) ON DUPLICATE KEY UPDATE c4 = ROW(740, 750);
-- appoint INSERT target column
INSERT INTO t_grammer (c5, c1, c2) VALUES('{81,82}', 81, DEFAULT) ON DUPLICATE KEY UPDATE c2 = VALUES(c1);
INSERT INTO t_grammer (c3[1], c3[2], c1) VALUES(881, 882, 82) ON DUPLICATE KEY UPDATE c5 = VALUES(c3), c2 = VALUES(c3[1]);
INSERT INTO t_grammer (c1, c3, c4) VALUES(83, '{81, 82, 83}', ROW(810, 820)) ON DUPLICATE KEY UPDATE c4 = EXCLUDED.c4;
INSERT INTO t_grammer (c1, c3, c4.a) VALUES(84, '{81, 82, 83}', 850) ON DUPLICATE KEY UPDATE c4.b = c3[3];
-- support UPDATE NOTHING
INSERT INTO t_grammer VALUES(91, 1, '{91, 92, 93}', ROW(94, 95)) ON DUPLICATE KEY UPDATE NOTHING;
INSERT INTO t_grammer (c5, c1, c2, c4) VALUES('{91,92}', 92, DEFAULT, ROW(910, 920)) ON DUPLICATE KEY UPDATE NOTHING;
-- UPDATE target: unsupport with schema but support with tablename
INSERT INTO t_grammer VALUES(0, 0, '{0,0}', ROW(0, 0), '{107, 108}') ON DUPLICATE KEY UPDATE
upsert_test.t_grammer.c2 = c2 * 10, upsert_test.t_grammer.c3[1:2] = c5[1:2], upsert_test.t_grammer.c4.a = c1;
INSERT INTO t_grammer VALUES(101, 1, '{102, 103, 104}', ROW(105, 106), '{107, 108}') ON DUPLICATE KEY UPDATE
t_grammer.c2 = c2 * 10, t_grammer.c3[1:2] = c5[1:2], t_grammer.c4.a = c1;
-- INSERT target: appoint schema
INSERT INTO upsert_test.t_grammer VALUES(102, 2, '{102, 103, 104}', ROW(105, 106), '{107, 108}') ON DUPLICATE KEY UPDATE
t_grammer.c2 = EXCLUDED.c2 * 10, t_grammer.c3[1:2] = c5[1:2], t_grammer.c4.a = VALUES(c1);
CREATE SCHEMA upsert_test_tmpschema;
SET CURRENT_SCHEMA TO upsert_test_tmpschema;
INSERT INTO upsert_test.t_grammer VALUES(103, 3, '{102, 103, 104}', ROW(105, 106), '{107, 108}') ON DUPLICATE KEY UPDATE
t_grammer.c2 = EXCLUDED.c2 * 10, t_grammer.c3[1:2] = c5[1:2], t_grammer.c4.a = VALUES(c1);
SET CURRENT_SCHEMA TO upsert_test;
DROP SCHEMA upsert_test_tmpschema;
-- support data type
INSERT INTO t_data VALUES(11, 11, 11, 11, 11, '11', '11', '11', '2020-04-23', '2020-04-23 11:00', '1:00') ON DUPLICATE KEY UPDATE NOTHING;
INSERT INTO t_data VALUES(12, 12, 12, 12, 12, '12', '12', '12', '2020-04-24', '2020-04-24 11:00', '2:00')
ON DUPLICATE KEY UPDATE
c_tiny = 13, c_smallint = 13, c_bigint = 13, c_numeric = 13,
c_var = '13', c_text = '13', c_bytea = '13', c_date = '2020-05-24', c_timestamp = '2020-05-24 11:00', c_time = '3:00';
INSERT INTO t_data VALUES(13, 13, 13, 13, 13, '13', '13', '13', '2020-04-25', '2020-04-25 11:00', '4:00')
ON DUPLICATE KEY UPDATE
c_tiny = EXCLUDED.c_tiny + 1, c_smallint = EXCLUDED.c_smallint + 1, c_bigint = EXCLUDED.c_bigint + 1, c_numeric = EXCLUDED.c_numeric + 1,
c_var = EXCLUDED.c_var || '3', c_text = EXCLUDED.c_text || '3', c_bytea = EXCLUDED.c_bytea || '3',
c_date = EXCLUDED.c_date + '1 day'::interval, c_timestamp = EXCLUDED.c_timestamp + '1 day'::interval, c_time = EXCLUDED.c_time + '1 hour'::interval;
-- support UPDATE to default
INSERT INTO t_default DEFAULT VALUES ON DUPLICATE KEY UPDATE c2 = 100, c3 = '2020-05-17';
INSERT INTO t_default VALUES(91, 0.91, '2020-05-17') ON DUPLICATE KEY UPDATE c2 = DEFAULT, c3 = DEFAULT;
INSERT INTO t_default VALUES(92, DEFAULT, '2020-05-17') ON DUPLICATE KEY UPDATE c2 = 10, c3 = DEFAULT;
-- unsupport alias
INSERT INTO t_grammer AS alias VALUES (91) ON DUPLICATE KEY UPDATE c2 = VALUES(c1);
-- unsupport VALUES with expr
INSERT INTO t_grammer VALUES(0, 0) ON DUPLICATE KEY UPDATE c2 = sqrt(VALUES(c2));
INSERT INTO t_grammer VALUES(0, 0) ON DUPLICATE KEY UPDATE c2 = VALUES(c3[1]) + 1;
INSERT INTO t_grammer VALUES(0, 0) ON DUPLICATE KEY UPDATE c2 = VALUES(c4.a) + 1;
INSERT INTO t_grammer VALUES(0, 0) ON DUPLICATE KEY UPDATE c2 = VALUES(t_grammer.c3[1]) + 1;
-- unsupport VALUES with table name
INSERT INTO t_grammer VALUES(0, 0) ON DUPLICATE KEY UPDATE c2 = VALUES(t_grammer.c4.a);
INSERT INTO t_grammer VALUES(0, 0) ON DUPLICATE KEY UPDATE c2 = VALUES(t_grammer.c2);
-- unsupport DEFAULT with expr
INSERT INTO t_grammer VALUES(0, 0) ON DUPLICATE KEY UPDATE c2 = DEFAULT + 1;
-- unsupport user defined typed column's element
INSERT INTO t_grammer VALUES(0, 0) ON DUPLICATE KEY UPDATE c2 = VALUES(c4.a);
INSERT INTO t_grammer VALUES(0, 0) ON DUPLICATE KEY UPDATE c2 = EXCLUDED.c4.a;
INSERT INTO t_grammer VALUES(0, 0) ON DUPLICATE KEY UPDATE c2 = c4.a;
SELECT * FROM t_data ORDER BY 1;
SELECT * FROM t_grammer ORDER BY 1;
SELECT * FROM t_default ORDER BY 1;

View File

@ -0,0 +1,113 @@
\c upsert
SET CURRENT_SCHEMA TO upsert_test;
-- enable_upsert_to_merge must be off, or upsert will be translated to merge.
SET enable_upsert_to_merge TO OFF;
SHOW enable_upsert_to_merge;
-- support multiple set
INSERT INTO t_grammer VALUES(11, 1) ON DUPLICATE KEY UPDATE c2 = 2, c4 = ROW(10, 20), c3 = '{10, 20, 30}';
INSERT INTO t_grammer VALUES(12, 2) ON DUPLICATE KEY UPDATE c2 = 2, c3[1] = 3;
-- support const value and expr
INSERT INTO t_grammer VALUES(23) ON DUPLICATE KEY UPDATE c2 = 2;
INSERT INTO t_grammer VALUES(24) ON DUPLICATE KEY UPDATE c2 = length('test') + 100;
-- support without table name
INSERT INTO t_grammer VALUES(31, 1) ON DUPLICATE KEY UPDATE c2 = c1, c4.a = VALUES(c1);
INSERT INTO t_grammer VALUES(32, 2) ON DUPLICATE KEY UPDATE c2 = c1 + 5, c4.a = VALUES(c1);
-- support with table name
INSERT INTO t_grammer VALUES(41, 1) ON DUPLICATE KEY UPDATE c2 = t_grammer.c1, c4.a = VALUES(c1);
INSERT INTO t_grammer VALUES(42, 2) ON DUPLICATE KEY UPDATE c2 = t_grammer.c1 + 5, c4.a = VALUES(c1);
-- support EXCLUDED alone and with expr
INSERT INTO t_grammer VALUES(51, 1) ON DUPLICATE KEY UPDATE c2 = c1 + 5, c4.a = EXCLUDED.c1;
INSERT INTO t_grammer VALUES(52, 2) ON DUPLICATE KEY UPDATE c2 = t_grammer.c1 + 5, c4.a = EXCLUDED.c1 + 5;
INSERT INTO t_grammer VALUES(53, 3) ON DUPLICATE KEY UPDATE c4.a = sqrt(EXCLUDED.c1 - EXCLUDED.c2 - 1) + 1, c2 = t_grammer.c1 + 5;
INSERT INTO t_grammer VALUES(54, 4) ON DUPLICATE KEY UPDATE c4.b = EXCLUDED.c1 + t_grammer.c1;
INSERT INTO t_grammer VALUES(55, 5) ON DUPLICATE KEY UPDATE c4.a = EXCLUDED.c2, c4.b = EXCLUDED.c1 + sqrt(c1 - 6);
-- support ARRAY
INSERT INTO t_grammer VALUES(61, 1) ON DUPLICATE KEY UPDATE c2 = VALUES(c3[1]);
INSERT INTO t_grammer VALUES(62, 2) ON DUPLICATE KEY UPDATE c5 = VALUES(c3[2,3]);
INSERT INTO t_grammer VALUES(63, 3) ON DUPLICATE KEY UPDATE c5 = VALUES(c3[2:3]);
INSERT INTO t_grammer VALUES(64, 4, '{10, 20, 30}') ON DUPLICATE KEY UPDATE c2 = EXCLUDED.c3[1];
INSERT INTO t_grammer VALUES(65, 5, '{10, 20, 30}') ON DUPLICATE KEY UPDATE c5 = EXCLUDED.c3[2,3];
INSERT INTO t_grammer VALUES(66, 6, '{10, 20, 30}') ON DUPLICATE KEY UPDATE c5 = EXCLUDED.c3[1:2];
INSERT INTO t_grammer VALUES(67, 7, '{10, 20, 30}') ON DUPLICATE KEY UPDATE c2 = c3[1];
INSERT INTO t_grammer VALUES(68, 8, '{10, 20, 30}') ON DUPLICATE KEY UPDATE c5 = c3[2,3];
INSERT INTO t_grammer VALUES(69, 9, '{10, 20, 30}') ON DUPLICATE KEY UPDATE c5 = c3[1:2];
-- support user defined type
INSERT INTO t_grammer VALUES(71, 1) ON DUPLICATE KEY UPDATE c4.a = c3[1] + c1;
INSERT INTO t_grammer VALUES(72, 2, '{71, 72, 73}') ON DUPLICATE KEY UPDATE c4.a = c3[1] + c1;
INSERT INTO t_grammer VALUES(73, 3, '{71, 72, 73}') ON DUPLICATE KEY UPDATE c4.a = c3[1] + c1, c4.b = c3[2];
INSERT INTO t_grammer VALUES(74, 4, '{71, 72, 73}', ROW(74, 75)) ON DUPLICATE KEY UPDATE c4 = ROW(740, 750);
-- appoint INSERT target column
INSERT INTO t_grammer (c5, c1, c2) VALUES('{81,82}', 81, DEFAULT) ON DUPLICATE KEY UPDATE c2 = VALUES(c1);
INSERT INTO t_grammer (c3[1], c3[2], c1) VALUES(881, 882, 82) ON DUPLICATE KEY UPDATE c5 = VALUES(c3), c2 = VALUES(c3[1]);
INSERT INTO t_grammer (c1, c3, c4) VALUES(83, '{81, 82, 83}', ROW(810, 820)) ON DUPLICATE KEY UPDATE c4 = EXCLUDED.c4;
INSERT INTO t_grammer (c1, c3, c4.a) VALUES(84, '{81, 82, 83}', 850) ON DUPLICATE KEY UPDATE c4.b = c3[3];
-- support UPDATE NOTHING
INSERT INTO t_grammer VALUES(91, 1, '{91, 92, 93}', ROW(94, 95)) ON DUPLICATE KEY UPDATE NOTHING;
INSERT INTO t_grammer (c5, c1, c2, c4) VALUES('{91,92}', 92, DEFAULT, ROW(910, 920)) ON DUPLICATE KEY UPDATE NOTHING;
-- UPDATE target: unsupport with schema but support with tablename
INSERT INTO t_grammer VALUES(0, 0, '{0,0}', ROW(0, 0), '{107, 108}') ON DUPLICATE KEY UPDATE
upsert_test.t_grammer.c2 = c2 * 10, upsert_test.t_grammer.c3[1:2] = c5[1:2], upsert_test.t_grammer.c4.a = c1;
INSERT INTO t_grammer VALUES(101, 1, '{102, 103, 104}', ROW(105, 106), '{107, 108}') ON DUPLICATE KEY UPDATE
t_grammer.c2 = c2 * 10, t_grammer.c3[1:2] = c5[1:2], t_grammer.c4.a = c1;
-- INSERT target: appoint schema
INSERT INTO upsert_test.t_grammer VALUES(102, 2, '{102, 103, 104}', ROW(105, 106), '{107, 108}') ON DUPLICATE KEY UPDATE
t_grammer.c2 = EXCLUDED.c2 * 10, t_grammer.c3[1:2] = c5[1:2], t_grammer.c4.a = VALUES(c1);
CREATE SCHEMA upsert_test_tmp;
SET CURRENT_SCHEMA TO upsert_test_tmp;
INSERT INTO upsert_test.t_grammer VALUES(103, 3, '{102, 103, 104}', ROW(105, 106), '{107, 108}') ON DUPLICATE KEY UPDATE
t_grammer.c2 = EXCLUDED.c2 * 10, t_grammer.c3[1:2] = c5[1:2], t_grammer.c4.a = VALUES(c1);
SET CURRENT_SCHEMA TO upsert_test;
DROP SCHEMA upsert_test_tmp;
-- support data type
INSERT INTO t_data VALUES(11, 11, 11, 11, 11, '11', '11', '11', '2020-04-23', '2020-04-23 11:00', '1:00') ON DUPLICATE KEY UPDATE NOTHING;
INSERT INTO t_data VALUES(12, 12, 12, 12, 12, '12', '12', '12', '2020-04-24', '2020-04-24 11:00', '2:00')
ON DUPLICATE KEY UPDATE
c_tiny = 13, c_smallint = 13, c_bigint = 13, c_numeric = 13,
c_var = '13', c_text = '13', c_bytea = '13', c_date = '2020-05-24', c_timestamp = '2020-05-24 11:00', c_time = '3:00';
INSERT INTO t_data VALUES(13, 13, 13, 13, 13, '13', '13', '13', '2020-04-25', '2020-04-25 11:00', '4:00')
ON DUPLICATE KEY UPDATE
c_tiny = EXCLUDED.c_tiny + 1, c_smallint = EXCLUDED.c_smallint + 1, c_bigint = EXCLUDED.c_bigint + 1, c_numeric = EXCLUDED.c_numeric + 1,
c_var = EXCLUDED.c_var || '3', c_text = EXCLUDED.c_text || '3', c_bytea = EXCLUDED.c_bytea || '3',
c_date = EXCLUDED.c_date + '1 day'::interval, c_timestamp = EXCLUDED.c_timestamp + '1 day'::interval, c_time = EXCLUDED.c_time + '1 hour'::interval;
-- support UPDATE to default
INSERT INTO t_default DEFAULT VALUES ON DUPLICATE KEY UPDATE c2 = 100, c3 = '2020-05-17';
INSERT INTO t_default VALUES(91, 0.91, '2020-05-17') ON DUPLICATE KEY UPDATE c2 = DEFAULT, c3 = DEFAULT;
INSERT INTO t_default VALUES(92, DEFAULT, '2020-05-17') ON DUPLICATE KEY UPDATE c2 = 10, c3 = DEFAULT;
-- unsupport alias
INSERT INTO t_grammer AS alias VALUES (91) ON DUPLICATE KEY UPDATE c2 = VALUES(c1);
-- unsupport VALUES with expr
INSERT INTO t_grammer VALUES(0, 0) ON DUPLICATE KEY UPDATE c2 = sqrt(VALUES(c2));
INSERT INTO t_grammer VALUES(0, 0) ON DUPLICATE KEY UPDATE c2 = VALUES(c3[1]) + 1;
INSERT INTO t_grammer VALUES(0, 0) ON DUPLICATE KEY UPDATE c2 = VALUES(c4.a) + 1;
INSERT INTO t_grammer VALUES(0, 0) ON DUPLICATE KEY UPDATE c2 = VALUES(t_grammer.c3[1]) + 1;
-- unsupport VALUES with table name
INSERT INTO t_grammer VALUES(0, 0) ON DUPLICATE KEY UPDATE c2 = VALUES(t_grammer.c4.a);
INSERT INTO t_grammer VALUES(0, 0) ON DUPLICATE KEY UPDATE c2 = VALUES(t_grammer.c2);
-- unsupport DEFAULT with expr
INSERT INTO t_grammer VALUES(0, 0) ON DUPLICATE KEY UPDATE c2 = DEFAULT + 1;
-- unsupport user defined typed column's element
INSERT INTO t_grammer VALUES(0, 0) ON DUPLICATE KEY UPDATE c2 = VALUES(c4.a);
INSERT INTO t_grammer VALUES(0, 0) ON DUPLICATE KEY UPDATE c2 = EXCLUDED.c4.a;
INSERT INTO t_grammer VALUES(0, 0) ON DUPLICATE KEY UPDATE c2 = c4.a;
SELECT * FROM t_data ORDER BY 1;
SELECT * FROM t_grammer ORDER BY 1;
SELECT * FROM t_default ORDER BY 1;

View File

@ -0,0 +1,76 @@
-- Note: about upsert test
-- test point:
-- grammer
-- table, unlogged table, temp table, matview
-- constraint(primary key, index, foreign key, null ...)
-- trigger
-- sequence
CREATE DATABASE upsert WITH TEMPLATE template0 ENCODING 'UTF8';
\c upsert
-- grammer test
CREATE SCHEMA upsert_test;
SET CURRENT_SCHEMA TO upsert_test;
CREATE TYPE atype AS(a int, b int);
CREATE TYPE btype AS(a int, b atype, c varchar[3]);
CREATE TABLE t_grammer (c1 INT PRIMARY KEY, c2 INT DEFAULT -100, c3 int[3], c4 atype, c5 int[2]);
CREATE TABLE t_default (c1 INT PRIMARY KEY DEFAULT 10, c2 FLOAT DEFAULT random(), c3 TIMESTAMP DEFAULT current_timestamp);
CREATE TABLE t_data (c_int INT PRIMARY KEY, c_tiny TINYINT, c_smallint SMALLINT, c_bigint BIGINT, c_numeric NUMERIC,
c_var VARCHAR, c_text TEXT, c_bytea BYTEA, c_date DATE, c_timestamp TIMESTAMP, c_time TIME,
c_intarray INT[3], c_com atype);
CREATE TABLE t_trigger (key INT PRIMARY KEY, color TEXT);
-- unlogged table
CREATE SCHEMA upsert_test_unlog;
SET CURRENT_SCHEMA TO upsert_test_unlog;
CREATE TYPE atype AS(a int, b int);
CREATE TYPE btype AS(a int, b atype, c varchar[3]);
CREATE UNLOGGED TABLE t_hash_unlog_0 (c1 INT, c2 INT, c3 VARCHAR, c4 INT[3], c5 INT[5], c6 atype, c7 btype);
CREATE UNLOGGED TABLE t_hash_unlog_1 (c1 INT, c2 INT PRIMARY KEY, c3 VARCHAR, c4 INT[3], c5 INT[5], c6 atype, c7 btype);
CREATE UNLOGGED TABLE t_rep_unlog_0 (c1 INT, c2 INT, c3 VARCHAR, c4 INT[3], c5 INT[5], c6 atype, c7 btype) ;
CREATE UNLOGGED TABLE t_rep_unlog_1 (c1 INT, c2 INT PRIMARY KEY, c3 VARCHAR, c4 INT[3], c5 INT[5], c6 atype, c7 btype);
-- temp table
-- temp table can not be created here, we create it in upsert_tmp_test.
-- restriction test
CREATE SCHEMA upsert_test_etc;
SET CURRENT_SCHEMA TO upsert_test_etc;
create table up_neg_01 (c1 int, c2 int, c3 int) with (ORIENTATION = COLUMN);
create table up_neg_02 (c1 int, c2 int, c3 int) with (ORIENTATION = COLUMN);
create table up_neg_03 (c1 int, c2 int UNIQUE DEFERRABLE, c3 int);
create table up_neg_04 (c1 int, c2 int UNIQUE, c3 int);
create table up_neg_05(c1 int, c2 int, c3 int, c4 int unique, c5 int primary key, unique(c2,c3));
create table up_neg_0(c1 int, c2 int, c3 int, c4 int unique, c5 int primary key, unique(c2,c3)) ;
create table up_neg_06(c1 int, c2 int, c3 int unique) ;
create table up_neg_07(c1 int, c2 int, c3 int unique) ;
create table up_neg_08(c1 int, c2 int, c3 int unique) ;
create table up_neg_09(c1 int, c2 int, c3 int, unique(c2,c3)) ;
create table up_neg_10(c1 int, c2 int, c3 int, unique(c2,c3)) ;
create view up_view as select *from up_neg_01;
create materialized view mat_view as select *from up_neg_01;
create table pkt (a int primary key, b int, c int);
create table fkt (a int primary key, b int references pkt, c int);
-- procedure test
CREATE SCHEMA upsert_test_procedure;
-- explain test
CREATE SCHEMA upsert_test_explain;
SET CURRENT_SCHEMA TO upsert_test_explain;
create table up_expl_hash(c1 int, c2 int, c3 int unique) ;
create table up_expl_repl(c1 int, c2 int, c3 int unique) ;
create table up_expl_part(c1 int, c2 int, c3 int unique) ;
create unlogged table up_expl_unlog(c1 int, c2 int, c3 int unique) ;
create table up_expl_node(c1 int, c2 int, c3 int unique) ;
create table up_expl_repl(c1 int, c2 int, c3 int unique) ;
create table up_expl_repl2(c1 int, c2 int, c3 int, c4 int unique, c5 int primary key, unique(c2,c3));
-- create temp table up_expl_temp(c1 int, c2 int, c3 int unique);

View File

@ -0,0 +1,170 @@
/*
* upsert negative test cases
*
table cases
col table
ORC table
VIEW
MAT view
index
DEFERABLE index
insert stmt
returning
with
with recur
update stmt
VALUES with expr
update distribute key
update primary key
update unique key
update partition key
where clause
with clause
sub query
*/
--------------------------------------------------------------------------------------------
\c upsert
SET CURRENT_SCHEMA TO upsert_test_etc;
-- enable_upsert_to_merge must be off, or upsert will be translated to merge.
SET enable_upsert_to_merge TO OFF;
SHOW enable_upsert_to_merge;
insert into up_neg_04 select a,a,a from generate_series(1,20) as a;
insert into up_neg_05 select a,a,a,a,a from generate_series(1,20) as a;
insert into up_neg_06 select a,a,a from generate_series(1,20) as a;
insert into up_neg_07 select a,a,a from generate_series(1,20) as a;
insert into up_neg_08 select a,a,a from generate_series(1,20) as a;
insert into up_neg_09 select a,a,a from generate_series(1,20) as a;
insert into up_neg_10 select a,a,a from generate_series(1,20) as a;
-- table cases
---- col table
insert into up_neg_01 values(1,2,3) on duplicate key update c3 = 1;
---- ORC table
insert into up_neg_02 values(1,2,3) on duplicate key update c3 = 1;
---- VIEW
insert into up_view values(1) on duplicate key update c3 = 1;
-- matview
refresh materialized view mat_view;
insert into mat_view values(1) on duplicate key update c3 = 1;
-- index
---- DEFERABLE index
insert into up_neg_03 values(1,2,3) on duplicate key update c1 = 1;
insert into up_neg_03 values(1) on duplicate key update c1 = 1;
-- insert stmt
----returning
insert into up_neg_04 values(1,1,1) on duplicate key update c1 = 1 returning c1;
----with
with sub as (select *from up_neg_04)
insert into up_neg_04 select *from sub on duplicate key update c1 =1;
----with recur
with RECURSIVE sub as (select *from up_neg_04)
insert into up_neg_04 select *from sub on duplicate key update c1 =1;
with sub as (select *from up_neg_04)
insert into up_neg_04 select *from sub on duplicate key update c1 =1 returning c1;
-- update stmt
---- VALUES with expr
insert into up_neg_05 values(1,1,1,1) on duplicate key update c3 = values(1+100);
insert into up_neg_05 values(1,1,1,1) on duplicate key update c3 = values(100);
insert into up_neg_05 values(1,1,1,1,1) on duplicate key update c1 = 1;
---- update primary key
insert into up_neg_05 values(1,1,1,1,1) on duplicate key update c5 = 1;
---- update unique key
insert into up_neg_05 values(1,1,1,1,1) on duplicate key update c4 = 1;
insert into up_neg_05 values(1,1,1,1,1) on duplicate key update c2 = 1, c3=2;
insert into up_neg_05 values(1,1,1,1,1) on duplicate key update c2 = 1;
insert into up_neg_05 values(1,1,1,1,1) on duplicate key update c3 = 2;
insert into up_neg_05 values(1,1,1,1,1) on duplicate key update c1 =1, c2 = 1, c3=2, c4=1,c5=1;
---- where clause
insert into up_neg_05 values(1,1,1,1,1) on duplicate key update c4 = 1 where c1=1;
---- from clause
insert into up_neg_05 values(1,1,1,1,1) on duplicate key update c4 = 1 from up_neg_04 where c1=1;
---- sub query
insert into up_neg_05 values(1,1,1,1,1) on duplicate key update (c2) = (select c2 from up_neg_05);
---- update distribute key
insert into up_neg_06 values(101, 1, 1) on duplicate key update c3=101;
---- update partition key
insert into up_neg_07 values(101, 1, 300) on duplicate key update c3=101;
insert into up_neg_08 values(101, 1, 300) on duplicate key update c3=101;
insert into up_neg_09 values(101, 1, 1) on duplicate key update c3=101;
insert into up_neg_09 values(101, 1, 1) on duplicate key update c2=101;
insert into up_neg_09 values(101, 1, 1) on duplicate key update c2 =1,c3=101;
--update unique key mul type plans
EXPLAIN (VERBOSE on, COSTS off) insert into up_neg_10 values(101, 1, 300) on duplicate key update c1=101;
insert into up_neg_10 values(101, 1, 300) on duplicate key update c3=101;
--trigger
create table upsert_base
(c1 int primary key,
c2 varchar(100), --record the type
cold varchar(1024),
cnew varchar(1024) );
create table upsert_tri
(c1 int,
c2 varchar(100),
c3 int,
unique(c1,c3)
);
--S1 after trigger
CREATE OR REPLACE FUNCTION trig_after() RETURNS TRIGGER AS $emp_audit$
BEGIN
IF (TG_OP = 'INSERT') THEN
insert into upsert_base(c2,cnew) values('after insert',new.c2);
RETURN NEW;
ELSIF (TG_OP = 'UPDATE') THEN
insert into upsert_base(c2,cold,cnew) values('after update',old.c2,new.c2);
RETURN NEW;
END IF;
RETURN NULL;
END;
$emp_audit$ LANGUAGE plpgsql;
CREATE TRIGGER tri_after
AFTER UPDATE OR INSERT ON upsert_tri
FOR EACH ROW EXECUTE PROCEDURE trig_after();
--S2 before trigger
CREATE OR REPLACE FUNCTION trig_before() RETURNS TRIGGER AS $emp_audit$
BEGIN
IF (TG_OP = 'INSERT') THEN
insert into upsert_base(c2,cnew) values('before insert',new.c2);
RETURN NEW;
ELSIF (TG_OP = 'UPDATE') THEN
insert into upsert_base(c2,cold,cnew) values('before update',old.c2,new.c2);
RETURN NEW;
END IF;
RETURN NULL;
END;
$emp_audit$ LANGUAGE plpgsql;
CREATE TRIGGER tri_before
BEFORE UPDATE OR INSERT ON upsert_tri
FOR EACH ROW EXECUTE PROCEDURE trig_before();
---- upsert-insert
insert into upsert_tri(c1,c2,c3) values(1000,'abc',1) on duplicate key update nothing;
insert into upsert_tri(c1,c2,c3) values(2000,'abc',1) on duplicate key update c2='bcd';
---- upsert-nothing
insert into upsert_tri(c1,c2,c3) values(1000,'abc',1) on duplicate key update nothing;
---- upsert-update
insert into upsert_tri(c1,c2,c3) values(2000,'abc',1) on duplicate key update c2='bcd';
---- check results
SELECT * from upsert_tri;
SELECT * from upsert_base;
-- foreign key
insert into pkt values(1,1,1),(2,2,2),(3,3,3),(4,4,4),(5,5,5);
insert into fkt values(1,1,1),(2,2,2),(3,3,3);
insert into fkt values(1,1,1),(2,2,2),(3,3,3) on duplicate key update b=excluded.b+1, c=0;
insert into fkt values(1,1,1),(2,2,2),(3,3,3) on duplicate key update b=excluded.b+3, c=-1;

View File

@ -0,0 +1,99 @@
\c upsert
CREATE SCHEMA upsert_test_tmp;
SET CURRENT_SCHEMA TO upsert_test_tmp;
CREATE TYPE atype AS(a int, b int);
CREATE TYPE btype AS(a int, b atype, c varchar[3]);
CREATE TEMP TABLE t_hash_tmp_0 (c1 INT, c2 INT, c3 VARCHAR, c4 INT[3], c5 INT[5], c6 atype, c7 btype);
CREATE TEMP TABLE t_hash_tmp_1 (c1 INT, c2 INT PRIMARY KEY, c3 VARCHAR, c4 INT[3], c5 INT[5], c6 atype, c7 btype);
CREATE TEMP TABLE t_rep_tmp_0 (c1 INT, c2 INT, c3 VARCHAR, c4 INT[3], c5 INT[5], c6 atype, c7 btype) ;
CREATE TEMP TABLE t_rep_tmp_1 (c1 INT, c2 INT PRIMARY KEY, c3 VARCHAR, c4 INT[3], c5 INT[5], c6 atype, c7 btype) ;
-- enable_upsert_to_merge must be off, or upsert will be translated to merge.
SET enable_upsert_to_merge TO OFF;
SHOW enable_upsert_to_merge;
-- hash table
-- tmp table without primary key
INSERT INTO t_hash_tmp_0 VALUES(1, 1, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}')),
(1, 2, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}'))
ON DUPLICATE KEY UPDATE NOTHING;
INSERT INTO t_hash_tmp_0 VALUES(2, 3, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}')),
(2, 4, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}'))
ON DUPLICATE KEY UPDATE c2 = 100;
-- tmp table with primary key
-- multi insert
INSERT INTO t_hash_tmp_1 VALUES(1, 1, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}')),
(1, 2, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}'))
ON DUPLICATE KEY UPDATE NOTHING;
INSERT INTO t_hash_tmp_1 VALUES(2, 3, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}')),
(2, 4, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}'))
ON DUPLICATE KEY UPDATE c1 = EXCLUDED.c1, c3 = EXCLUDED.c3, c4 = EXCLUDED.c4, c5 = EXCLUDED.c5, c6 = EXCLUDED.c6, c7 = EXCLUDED.c7;
SELECT * FROM t_hash_tmp_1 ORDER BY c2;
INSERT INTO t_hash_tmp_1 VALUES(10, 1, 'C30', '{10,20,30}', '{100,200,300,400,500}', ROW(100,200), ROW(1000, ROW(100,200), '{1000,2000}')),
(11, 2, 'C31', '{11,21,31}', '{101,201,301,401,501}', ROW(101,201), ROW(1001, ROW(101,201), '{1001,2001}'))
ON DUPLICATE KEY UPDATE NOTHING;
INSERT INTO t_hash_tmp_1 VALUES(20, 3, 'C30', '{10,20,30}', '{10,20,30,40,50}', ROW(100,200), ROW(1000, ROW(100,200), '{1000,2000}')),
(21, 4, 'C31', '{11,21,31}', '{101,201,301,401,501}', ROW(101,201), ROW(1001, ROW(101,201), '{1001,2001}'))
ON DUPLICATE KEY UPDATE c1 = EXCLUDED.c1, c3 = EXCLUDED.c3, c4 = EXCLUDED.c4, c5 = EXCLUDED.c5, c6 = EXCLUDED.c6, c7 = EXCLUDED.c7;
SELECT * FROM t_hash_tmp_1 ORDER BY c2;
-- insert and update same tuple, and update twice for another same tuple
INSERT INTO t_hash_tmp_1 VALUES(0, 5, 'C30', '{10,20,30}', '{10,20,30,40,50}', ROW(100,200), ROW(1000, ROW(100,200), '{1000,2000}')),
(1, 5, 'C31', '{11,21,31}', '{101,201,301,401,501}', ROW(101,201), ROW(1001, ROW(101,201), '{1001,2001}')),
(10, 1, 'C30', '{10,20,30}', '{100,200,300,400,500}', ROW(100,200), ROW(1000, ROW(100,200), '{1000,2000}')),
(11, 1, 'C31', '{11,21,31}', '{101,201,301,401,501}', ROW(101,201), ROW(1001, ROW(101,201), '{1001,2001}'))
ON DUPLICATE KEY UPDATE NOTHING;
SELECT * FROM t_hash_tmp_1 ORDER BY c2;
INSERT INTO t_hash_tmp_1 VALUES(0, 5, 'C30', '{10,20,30}', '{10,20,30,40,50}', ROW(100,200), ROW(1000, ROW(100,200), '{1000,2000}')),
(1, 5, 'C31', '{11,21,31}', '{101,201,301,401,501}', ROW(101,201), ROW(1001, ROW(101,201), '{1001,2001}')),
(10, 1, 'C30', '{10,20,30}', '{100,200,300,400,500}', ROW(100,200), ROW(1000, ROW(100,200), '{1000,2000}')),
(11, 1, 'C31', '{11,21,31}', '{101,201,301,401,501}', ROW(101,201), ROW(1001, ROW(101,201), '{1001,2001}'))
ON DUPLICATE KEY UPDATE c1 = EXCLUDED.c1, c3 = EXCLUDED.c3, c4 = EXCLUDED.c4, c5 = EXCLUDED.c5, c6 = EXCLUDED.c6, c7 = EXCLUDED.c7;
SELECT * FROM t_hash_tmp_1 ORDER BY c2;
-- replication table
-- tmp table without primary key
INSERT INTO t_rep_tmp_0 VALUES(1, 1, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}')),
(1, 2, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}'))
ON DUPLICATE KEY UPDATE NOTHING;
INSERT INTO t_rep_tmp_0 VALUES(2, 3, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}')),
(2, 4, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}'))
ON DUPLICATE KEY UPDATE c2 = 100;
-- tmp table with primary key
-- multi insert
INSERT INTO t_rep_tmp_1 VALUES(1, 1, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}')),
(1, 2, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}'))
ON DUPLICATE KEY UPDATE NOTHING;
INSERT INTO t_rep_tmp_1 VALUES(2, 3, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}')),
(2, 4, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}'))
ON DUPLICATE KEY UPDATE c1 = EXCLUDED.c1, c3 = EXCLUDED.c3, c4 = EXCLUDED.c4, c5 = EXCLUDED.c5, c6 = EXCLUDED.c6, c7 = EXCLUDED.c7;
SELECT * FROM t_rep_tmp_1 ORDER BY c2;
INSERT INTO t_rep_tmp_1 VALUES(10, 1, 'C30', '{10,20,30}', '{100,200,300,400,500}', ROW(100,200), ROW(1000, ROW(100,200), '{1000,2000}')),
(11, 2, 'C31', '{11,21,31}', '{101,201,301,401,501}', ROW(101,201), ROW(1001, ROW(101,201), '{1001,2001}'))
ON DUPLICATE KEY UPDATE NOTHING;
INSERT INTO t_rep_tmp_1 VALUES(20, 3, 'C30', '{10,20,30}', '{10,20,30,40,50}', ROW(100,200), ROW(1000, ROW(100,200), '{1000,2000}')),
(21, 4, 'C31', '{11,21,31}', '{101,201,301,401,501}', ROW(101,201), ROW(1001, ROW(101,201), '{1001,2001}'))
ON DUPLICATE KEY UPDATE c1 = EXCLUDED.c1, c3 = EXCLUDED.c3, c4 = EXCLUDED.c4, c5 = EXCLUDED.c5, c6 = EXCLUDED.c6, c7 = EXCLUDED.c7;
SELECT * FROM t_rep_tmp_1 ORDER BY c2;
-- insert and update same tuple, and update twice for another same tuple
INSERT INTO t_rep_tmp_1 VALUES(0, 5, 'C30', '{10,20,30}', '{10,20,30,40,50}', ROW(100,200), ROW(1000, ROW(100,200), '{1000,2000}')),
(1, 5, 'C31', '{11,21,31}', '{101,201,301,401,501}', ROW(101,201), ROW(1001, ROW(101,201), '{1001,2001}')),
(10, 1, 'C30', '{10,20,30}', '{100,200,300,400,500}', ROW(100,200), ROW(1000, ROW(100,200), '{1000,2000}')),
(11, 1, 'C31', '{11,21,31}', '{101,201,301,401,501}', ROW(101,201), ROW(1001, ROW(101,201), '{1001,2001}'))
ON DUPLICATE KEY UPDATE NOTHING;
SELECT * FROM t_rep_tmp_1 ORDER BY c2;
INSERT INTO t_rep_tmp_1 VALUES(0, 5, 'C30', '{10,20,30}', '{10,20,30,40,50}', ROW(100,200), ROW(1000, ROW(100,200), '{1000,2000}')),
(1, 5, 'C31', '{11,21,31}', '{101,201,301,401,501}', ROW(101,201), ROW(1001, ROW(101,201), '{1001,2001}')),
(10, 1, 'C30', '{10,20,30}', '{100,200,300,400,500}', ROW(100,200), ROW(1000, ROW(100,200), '{1000,2000}')),
(11, 1, 'C31', '{11,21,31}', '{101,201,301,401,501}', ROW(101,201), ROW(1001, ROW(101,201), '{1001,2001}'))
ON DUPLICATE KEY UPDATE c1 = EXCLUDED.c1, c3 = EXCLUDED.c3, c4 = EXCLUDED.c4, c5 = EXCLUDED.c5, c6 = EXCLUDED.c6, c7 = EXCLUDED.c7;
SELECT * FROM t_rep_tmp_1 ORDER BY c2;
DROP SCHEMA upsert_test_tmp CASCADE;

View File

@ -0,0 +1,63 @@
\c upsert
SET CURRENT_SCHEMA TO upsert_test;
-- enable_upsert_to_merge must be off, or upsert will be translated to merge.
SET enable_upsert_to_merge TO OFF;
SHOW enable_upsert_to_merge;
CREATE FUNCTION upsert_before_func()
RETURNS TRIGGER language plpgsql AS
$$
BEGIN
IF (TG_OP = 'UPDATE') THEN
RAISE warning 'before update (old): %', old.*::TEXT;
RAISE warning 'before update (new): %', new.*::TEXT;
elsIF (TG_OP = 'INSERT') THEN
RAISE warning 'before insert (new): %', new.*::TEXT;
IF NEW.key % 2 = 0 THEN
NEW.color := NEW.color || ' trig modified';
RAISE warning 'before insert (new, modified): %', new.*::TEXT;
END IF;
END IF;
RETURN new;
END;
$$;
CREATE TRIGGER upsert_before_trig BEFORE INSERT OR UPDATE ON t_trigger
FOR EACH ROW EXECUTE procedure upsert_before_func();
CREATE FUNCTION upsert_after_func()
RETURNS TRIGGER language plpgsql AS
$$
BEGIN
IF (TG_OP = 'UPDATE') THEN
RAISE warning 'after update (old): %', old.*::TEXT;
RAISE warning 'after update (new): %', new.*::TEXT;
elsIF (TG_OP = 'INSERT') THEN
RAISE warning 'after insert (new): %', new.*::TEXT;
END IF;
RETURN null;
END;
$$;
CREATE TRIGGER upsert_after_trig AFTER INSERT OR UPDATE ON t_trigger
FOR EACH ROW EXECUTE procedure upsert_after_func();
INSERT INTO t_trigger values(1, 'black') ON DUPLICATE KEY UPDATE color = 'updated ' || t_trigger.color;
INSERT INTO t_trigger values(2, 'red') ON DUPLICATE KEY UPDATE color = 'updated ' || t_trigger.color;
INSERT INTO t_trigger values(3, 'orange') ON DUPLICATE KEY UPDATE color = 'updated ' || t_trigger.color;
INSERT INTO t_trigger values(4, 'green') ON DUPLICATE KEY UPDATE color = 'updated ' || t_trigger.color;
INSERT INTO t_trigger values(5, 'purple') ON DUPLICATE KEY UPDATE color = 'updated ' || t_trigger.color;
INSERT INTO t_trigger values(6, 'white') ON DUPLICATE KEY UPDATE color = 'updated ' || t_trigger.color;
INSERT INTO t_trigger values(7, 'pink') ON DUPLICATE KEY UPDATE color = 'updated ' || t_trigger.color;
INSERT INTO t_trigger values(8, 'yellow') ON DUPLICATE KEY UPDATE color = 'updated ' || t_trigger.color;
SELECT * FROM t_trigger ORDER BY key;
INSERT INTO t_trigger values(2, 'black') ON DUPLICATE KEY UPDATE color = 'updated ' || t_trigger.color;
INSERT INTO t_trigger values(3, 'red') ON DUPLICATE KEY UPDATE color = 'updated ' || t_trigger.color;
INSERT INTO t_trigger values(4, 'orange') ON DUPLICATE KEY UPDATE color = 'updated ' || t_trigger.color;
INSERT INTO t_trigger values(5, 'green') ON DUPLICATE KEY UPDATE color = 'updated ' || t_trigger.color;
INSERT INTO t_trigger values(6, 'purple') ON DUPLICATE KEY UPDATE color = 'updated ' || t_trigger.color;
INSERT INTO t_trigger values(7, 'white') ON DUPLICATE KEY UPDATE color = 'updated ' || t_trigger.color;
INSERT INTO t_trigger values(8, 'pink') ON DUPLICATE KEY UPDATE color = 'updated ' || t_trigger.color;
INSERT INTO t_trigger values(9, 'yellow') ON DUPLICATE KEY UPDATE color = 'updated ' || t_trigger.color;
SELECT * FROM t_trigger ORDER BY key;

View File

@ -0,0 +1,89 @@
\c upsert
SET CURRENT_SCHEMA TO upsert_test_unlog;
-- enable_upsert_to_merge must be off, or upsert will be translated to merge.
SET enable_upsert_to_merge TO OFF;
SHOW enable_upsert_to_merge;
-- hash table
-- unlogged table without primary key
INSERT INTO t_hash_unlog_0 VALUES(1, 1, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}')),
(1, 2, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}'))
ON DUPLICATE KEY UPDATE NOTHING;
INSERT INTO t_hash_unlog_0 VALUES(2, 3, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}')),
(2, 4, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}'))
ON DUPLICATE KEY UPDATE c2 = 100;
-- unlogged table with primary key
-- multi insert
INSERT INTO t_hash_unlog_1 VALUES(1, 1, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}')),
(1, 2, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}'))
ON DUPLICATE KEY UPDATE NOTHING;
INSERT INTO t_hash_unlog_1 VALUES(2, 3, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}')),
(2, 4, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}'))
ON DUPLICATE KEY UPDATE c1 = EXCLUDED.c1, c3 = EXCLUDED.c3, c4 = EXCLUDED.c4, c5 = EXCLUDED.c5, c6 = EXCLUDED.c6, c7 = EXCLUDED.c7;
SELECT * FROM t_hash_unlog_1 ORDER BY c2;
INSERT INTO t_hash_unlog_1 VALUES(10, 1, 'C30', '{10,20,30}', '{100,200,300,400,500}', ROW(100,200), ROW(1000, ROW(100,200), '{1000,2000}')),
(11, 2, 'C31', '{11,21,31}', '{101,201,301,401,501}', ROW(101,201), ROW(1001, ROW(101,201), '{1001,2001}'))
ON DUPLICATE KEY UPDATE NOTHING;
INSERT INTO t_hash_unlog_1 VALUES(20, 3, 'C30', '{10,20,30}', '{10,20,30,40,50}', ROW(100,200), ROW(1000, ROW(100,200), '{1000,2000}')),
(21, 4, 'C31', '{11,21,31}', '{101,201,301,401,501}', ROW(101,201), ROW(1001, ROW(101,201), '{1001,2001}'))
ON DUPLICATE KEY UPDATE c1 = EXCLUDED.c1, c3 = EXCLUDED.c3, c4 = EXCLUDED.c4, c5 = EXCLUDED.c5, c6 = EXCLUDED.c6, c7 = EXCLUDED.c7;
SELECT * FROM t_hash_unlog_1 ORDER BY c2;
-- insert and update same tuple, and update twice for another same tuple
INSERT INTO t_hash_unlog_1 VALUES(0, 5, 'C30', '{10,20,30}', '{10,20,30,40,50}', ROW(100,200), ROW(1000, ROW(100,200), '{1000,2000}')),
(1, 5, 'C31', '{11,21,31}', '{101,201,301,401,501}', ROW(101,201), ROW(1001, ROW(101,201), '{1001,2001}')),
(10, 1, 'C30', '{10,20,30}', '{100,200,300,400,500}', ROW(100,200), ROW(1000, ROW(100,200), '{1000,2000}')),
(11, 1, 'C31', '{11,21,31}', '{101,201,301,401,501}', ROW(101,201), ROW(1001, ROW(101,201), '{1001,2001}'))
ON DUPLICATE KEY UPDATE NOTHING;
SELECT * FROM t_hash_unlog_1 ORDER BY c2;
INSERT INTO t_hash_unlog_1 VALUES(0, 5, 'C30', '{10,20,30}', '{10,20,30,40,50}', ROW(100,200), ROW(1000, ROW(100,200), '{1000,2000}')),
(1, 5, 'C31', '{11,21,31}', '{101,201,301,401,501}', ROW(101,201), ROW(1001, ROW(101,201), '{1001,2001}')),
(10, 1, 'C30', '{10,20,30}', '{100,200,300,400,500}', ROW(100,200), ROW(1000, ROW(100,200), '{1000,2000}')),
(11, 1, 'C31', '{11,21,31}', '{101,201,301,401,501}', ROW(101,201), ROW(1001, ROW(101,201), '{1001,2001}'))
ON DUPLICATE KEY UPDATE c1 = EXCLUDED.c1, c3 = EXCLUDED.c3, c4 = EXCLUDED.c4, c5 = EXCLUDED.c5, c6 = EXCLUDED.c6, c7 = EXCLUDED.c7;
SELECT * FROM t_hash_unlog_1 ORDER BY c2;
-- replication table
-- unlogged table without primary key
INSERT INTO t_rep_unlog_0 VALUES(1, 1, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}')),
(1, 2, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}'))
ON DUPLICATE KEY UPDATE NOTHING;
INSERT INTO t_rep_unlog_0 VALUES(2, 3, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}')),
(2, 4, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}'))
ON DUPLICATE KEY UPDATE c2 = 100;
-- unlogged table with primary key
-- multi insert
INSERT INTO t_rep_unlog_1 VALUES(1, 1, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}')),
(1, 2, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}'))
ON DUPLICATE KEY UPDATE NOTHING;
INSERT INTO t_rep_unlog_1 VALUES(2, 3, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}')),
(2, 4, 'C3', '{1,2,3}', '{10,20,30,40,50}', ROW(10,20), ROW(100, ROW(10,20), '{100,200}'))
ON DUPLICATE KEY UPDATE c1 = EXCLUDED.c1, c3 = EXCLUDED.c3, c4 = EXCLUDED.c4, c5 = EXCLUDED.c5, c6 = EXCLUDED.c6, c7 = EXCLUDED.c7;
SELECT * FROM t_rep_unlog_1 ORDER BY c2;
INSERT INTO t_rep_unlog_1 VALUES(10, 1, 'C30', '{10,20,30}', '{100,200,300,400,500}', ROW(100,200), ROW(1000, ROW(100,200), '{1000,2000}')),
(11, 2, 'C31', '{11,21,31}', '{101,201,301,401,501}', ROW(101,201), ROW(1001, ROW(101,201), '{1001,2001}'))
ON DUPLICATE KEY UPDATE NOTHING;
INSERT INTO t_rep_unlog_1 VALUES(20, 3, 'C30', '{10,20,30}', '{10,20,30,40,50}', ROW(100,200), ROW(1000, ROW(100,200), '{1000,2000}')),
(21, 4, 'C31', '{11,21,31}', '{101,201,301,401,501}', ROW(101,201), ROW(1001, ROW(101,201), '{1001,2001}'))
ON DUPLICATE KEY UPDATE c1 = EXCLUDED.c1, c3 = EXCLUDED.c3, c4 = EXCLUDED.c4, c5 = EXCLUDED.c5, c6 = EXCLUDED.c6, c7 = EXCLUDED.c7;
SELECT * FROM t_rep_unlog_1 ORDER BY c2;
-- insert and update same tuple, and update twice for another same tuple
INSERT INTO t_rep_unlog_1 VALUES(0, 5, 'C30', '{10,20,30}', '{10,20,30,40,50}', ROW(100,200), ROW(1000, ROW(100,200), '{1000,2000}')),
(1, 5, 'C31', '{11,21,31}', '{101,201,301,401,501}', ROW(101,201), ROW(1001, ROW(101,201), '{1001,2001}')),
(10, 1, 'C30', '{10,20,30}', '{100,200,300,400,500}', ROW(100,200), ROW(1000, ROW(100,200), '{1000,2000}')),
(11, 1, 'C31', '{11,21,31}', '{101,201,301,401,501}', ROW(101,201), ROW(1001, ROW(101,201), '{1001,2001}'))
ON DUPLICATE KEY UPDATE NOTHING;
SELECT * FROM t_rep_unlog_1 ORDER BY c2;
INSERT INTO t_rep_unlog_1 VALUES(0, 5, 'C30', '{10,20,30}', '{10,20,30,40,50}', ROW(100,200), ROW(1000, ROW(100,200), '{1000,2000}')),
(1, 5, 'C31', '{11,21,31}', '{101,201,301,401,501}', ROW(101,201), ROW(1001, ROW(101,201), '{1001,2001}')),
(10, 1, 'C30', '{10,20,30}', '{100,200,300,400,500}', ROW(100,200), ROW(1000, ROW(100,200), '{1000,2000}')),
(11, 1, 'C31', '{11,21,31}', '{101,201,301,401,501}', ROW(101,201), ROW(1001, ROW(101,201), '{1001,2001}'))
ON DUPLICATE KEY UPDATE c1 = EXCLUDED.c1, c3 = EXCLUDED.c3, c4 = EXCLUDED.c4, c5 = EXCLUDED.c5, c6 = EXCLUDED.c6, c7 = EXCLUDED.c7;
SELECT * FROM t_rep_unlog_1 ORDER BY c2;