DROP SCHEMA test_insert_update_006 CASCADE;
ERROR:  schema "test_insert_update_006" does not exist
CREATE SCHEMA test_insert_update_006;
SET CURRENT_SCHEMA TO test_insert_update_006;
-- test t1 with no index
CREATE TEMPORARY TABLE t1 (
    col1 TEXT,
    col2 VARCHAR,
    col3 VARCHAR(10) DEFAULT '1'
--    col4 TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
--    col5 BIGSERIAL
) DISTRIBUTE BY hash(col1);
--- distribute key are not allowed to update
INSERT INTO t1 VALUES (1, 2) ON DUPLICATE KEY UPDATE col1 = 3;
ERROR:  Distributed key column can't be updated in current version
--- 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 col1, col2, col3;
 col1 | col2 | col3 
------+------+------
 1    | 2    | 1
 1    | 2    | 1
 1    |      | 3
 1    |      | 3
 2    | 1    | 1
 2    | 1    | 1
(6 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::INT + col2::INT + col3) * 10;
SELECT col1, col2, col3 FROM t1 ORDER BY col1, col2, col3;
 col1 | col2 | col3 
------+------+------
 1    | 1    | 1
 1    | 2    | 1
 1    | 2    | 1
 1    | 2    | 1
 1    | 3    | 1
 1    |      | 1
 1    |      | 3
 1    |      | 3
 2    | 1    | 1
 2    | 1    | 1
 2    | 1    | 1
(11 rows)

--- test subquery, should insert
INSERT INTO t1
    (SELECT col1 || col2 || '00' FROM t1 ORDER BY col1, col2)
    ON DUPLICATE KEY UPDATE col3 = col1 * 100;
SELECT col1, col2, col3 FROM t1 WHERE col1 >= 100 ORDER BY col1, col2, col3;
 col1 | col2 | col3 
------+------+------
 100  |      | 1
 100  |      | 1
 100  |      | 1
 1100 |      | 1
 1200 |      | 1
 1200 |      | 1
 1200 |      | 1
 1300 |      | 1
 2100 |      | 1
 2100 |      | 1
 2100 |      | 1
(11 rows)

-- test t2 with one primary key
CREATE TEMPORARY TABLE t2 (
    col1 INT,
    col2 TEXT PRIMARY KEY,
    col3 VARCHAR DEFAULT '1',
    col4 TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    col5 INTEGER(10, 5) DEFAULT RANDOM()
) DISTRIBUTE BY hash(col2);
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:  Distributed key column can't be updated in current version
INSERT INTO t2 VALUES (1, 1) ON DUPLICATE KEY UPDATE t2.col2 = 3;
ERROR:  Distributed key column can't be updated in current version
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:  Distributed key column can't be updated in current version
--- 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 col1, col2, col3;
 col1 | col2 | col3 |  col5  
------+------+------+--------
--?    1 | 1    | 1    | .14532
--?    2 | 2    | 1    | .50007
--?    3 | 3    | 1    | .92848
--?    4 | 4    | 1    | .56023
--?    5 | 5    | 1    | .50473
--?    6 | 6    | 1    | .62296
--?    7 | 7    | 1    | .83644
--?    8 | 8    | 1    | .15365
(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 + 1;
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 col1, col2, col3;
 col1 | col2 |  col3   |  col5  
------+------+---------+--------
--?    3 | 3    | 1.18280 | .18280
--?    4 | 4    | 1.40835 | .40835
--?    7 | 7    | 1       | .73914
--?    8 | 8    | 1       | .15058
--?   13 | 5    | 1       | .08230
--?   30 | 1    | 1.05704 | .05704
--?   40 | 2    | 1.38199 | .38199
--? 2103 | 6    | 1       | .26182
(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, col5 = 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 col1, col2, col3, col5 FROM t2 WHERE col2 = 9 OR col5 > 1 ORDER BY col1, col2, col3, col5;
 col1 | col2 | col3 |   col5   
------+------+------+----------
      | 10   | 10   | 10.00000
      | 20   | 20   | 20.00000
      | 30   | 30   | 30.00000
--?      | 9    | 9    |   .29441
(4 rows)

---- should update
INSERT INTO t2 (col2, col3) VALUES (9, 9) ON DUPLICATE KEY UPDATE col1 = 90, col5 = 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 col1, col2, col3, col5 FROM t2 WHERE col2 = 9 OR col5 > 1 ORDER BY col1, col2, col3, col5;
 col1 | col2 | col3 |   col5    
------+------+------+-----------
   90 | 9    | 9    |  90.00000
  100 | 10   | 100  | 100.00000
  100 | 20   | 100  | 100.00000
  100 | 30   | 100  | 100.00000
(4 rows)

--- test subquery
---- should insert
SELECT col1 * 1000, col2 * 1000 + 1 FROM t2 ORDER BY col1 LIMIT 2;
 ?column? | ?column? 
----------+----------
     3000 |     3001
     4000 |     4001
(2 rows)

SELECT col1, col2, col3 FROM t2 
    WHERE col1 >= (SELECT col1 * 1000 FROM t2 ORDER BY col1 LIMIT 1)
    ORDER BY col1, col2;
 col1 | col2 | col3 
------+------+------
(0 rows)

INSERT INTO t2
    (SELECT col1 * 1000, col2 * 1000 + 1 FROM t2 ORDER BY col1 LIMIT 2)
    ON DUPLICATE KEY UPDATE col3 = col1 + 1;
SELECT col1, col2, col3 FROM t2 
    WHERE col1 >= (SELECT col1 * 1000 FROM t2 ORDER BY col1 LIMIT 1)
    ORDER BY col1, col2;
 col1 | col2 | col3 
------+------+------
 3000 | 3001 | 1
 4000 | 4001 | 1
(2 rows)

---- should update
INSERT INTO t2
    (SELECT col1 * 1000, col2 * 1000 + 1 FROM t2 ORDER BY col1 LIMIT 2)
    ON DUPLICATE KEY UPDATE col3 = col2 + 1;
SELECT col1, col2, col3 FROM t2
    WHERE col1 >= (SELECT col1 * 1000 FROM t2 ORDER BY col1 LIMIT 1)
    ORDER BY col1, col2;
 col1 | col2 | col3 
------+------+------
 3000 | 3001 | 3002
 4000 | 4001 | 4002
(2 rows)

--- test subquery
--- should insert
SELECT col1 * 1000 + 2, col2 * 1000 FROM t2 ORDER BY col1 LIMIT 2 OFFSET 1;
 ?column? | ?column? 
----------+----------
     4002 |     4000
     7002 |     7000
(2 rows)

SELECT col1, col2, col3 FROM t2
    WHERE col2 >= (SELECT col1 * 1000 + 2 FROM t2 ORDER BY col1 LIMIT 1 OFFSET 1)
    ORDER BY col1, col2;
 col1 | col2 | col3 
------+------+------
(0 rows)

INSERT INTO t2 (col2, col3)
    (SELECT col1 * 1000 + 2, col2 * 1000 FROM t2 ORDER BY col1 LIMIT 2 OFFSET 1)
    ON DUPLICATE KEY UPDATE col3 = col2 + 1;
SELECT col1, col2, col3 FROM t2 
    WHERE col2 >= (SELECT col1 * 1000 + 2 FROM t2 ORDER BY col1 LIMIT 1 OFFSET 1)
    ORDER BY col1, col2;
 col1 | col2 | col3 
------+------+------
      | 4002 | 4000
      | 7002 | 7000
(2 rows)

-- should update
INSERT INTO t2 (col2, col3)
    (SELECT col1 * 1000 + 2, col2 * 1000 FROM t2 ORDER BY col1 LIMIT 2 OFFSET 1)
    ON DUPLICATE KEY UPDATE col3 = col2 + 1;
SELECT col1, col2, col3 FROM t2 
    WHERE col2 >= (SELECT col1 * 1000 + 2 FROM t2 ORDER BY col1 LIMIT 1 OFFSET 1)
    ORDER BY col1, col2;
 col1 | col2 | col3 
------+------+------
      | 4002 | 4003
      | 7002 | 7003
(2 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
 100  | 1
 1100 | 1
 1200 | 1
 1300 | 1
 2    | 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::FLOAT) * 10;
ERROR:  unable to get a stable set of rows in the source tables
set behavior_compat_options='merge_update_multi';
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::FLOAT) * 10;
SELECT col1, col2, col3 FROM t2 ORDER BY col1, col2, col3;
--? col1 | col2 |   col3   
--?
--?    3 | 3    | 75.5956
--?    4 | 4    | 1.51720
    7 | 7    | 1
    8 | 8    | 1
--?   13 | 5    | 1
--?   30 | 1    | 326.9148
--?   40 | 2    | 434.3598
   90 | 9    | 9
  100 | 10   | 100
  100 | 20   | 100
  100 | 30   | 100
--? 2103 | 6    | 1
 3000 | 3001 | 3002
 4000 | 4001 | 4002
      | 4002 | 4003
      | 7002 | 7003
(16 rows)

reset behavior_compat_options;
-- test t3 with one primary index with two columns
CREATE TEMPORARY TABLE t3 (
    col1 INT,
    col2 VARCHAR,
    col3 TEXT DEFAULT 1,
--    col4 TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    col5 TEXT,
    PRIMARY KEY (col2, col3)
)DISTRIBUTE BY hash(col2);
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:  Columns referenced in the primary or unique index cannot be updated: "t3"."col3"
--- 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 col1, col2, col3;
 col1 | col2 | col3 | col5 
------+------+------+------
    1 | 1    | 1    | 
    2 | 2    | 2    | 
(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 col1, col2, col3;
 col1 | col2 | col3 | col5 
------+------+------+------
    2 | 2    | 2    | 20
   10 | 1    | 1    | 
(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 col1, col2, col3;
 col1 | col2 | col3 | col5 
------+------+------+------
    2 | 2    | 2    | 20
   10 | 1    | 1    | 
      | 3    | 3    | 
(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 col1, col2, col3;
 col1 | col2 | col3 | col5 
------+------+------+------
    2 | 2    | 2    | 20
    6 | 3    | 3    | 
   10 | 1    | 1    | 
(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:  Columns referenced in the primary or unique index cannot be updated: "t3"."col3"
--- 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 col1, col2, col3;
 col1 | col2 | col3 | col5 
------+------+------+------
    1 |      | 1    | 
    1 |      | 1    | 
(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 col1, col2, col3;
 col1 | col2 | col3 | col5 
------+------+------+------
    1 | 1    | 1    | 
    1 |      | 1    | 
    1 |      | 1    | 
    2 | 2    | 2    | 
(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 col1, col2, col3;
 col1 | col2 | col3 | col5 
------+------+------+------
    1 |      | 1    | 
    1 |      | 1    | 
    2 | 2    | 2    | 20
   10 | 1    | 1    | 
(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 col1, col2, col3;
 col1 | col2 | col3 | col5 
------+------+------+------
    1 |      | 1    | 
    1 |      | 1    | 
    2 | 2    | 2    | 20
   10 | 1    | 1    | 
  100 |      | 2    | 
  100 |      | 2    | 
      | 3    | 3    | 
(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 col1, col2, col3;
 col1 | col2 | col3 | col5 
------+------+------+------
    1 |      | 1    | 
    1 |      | 1    | 
    2 | 2    | 2    | 20
    6 | 3    | 3    | 
   10 | 1    | 1    | 
  100 |      | 2    | 
  100 |      | 2    | 
(7 rows)

DROP SCHEMA test_insert_update_006 CASCADE;