SET search_path TO merge_arbitrary_schema;
INSERT INTO target_cj VALUES (1, 'target', 0);
INSERT INTO target_cj VALUES (2, 'target', 0);
INSERT INTO target_cj VALUES (2, 'target', 0);
INSERT INTO target_cj VALUES (3, 'target', 0);
INSERT INTO source_cj1 VALUES (2, 'source-1', 10);
INSERT INTO source_cj2 VALUES (2, 'source-2', 20);
BEGIN;
MERGE INTO target_cj t
USING source_cj1 s1 INNER JOIN source_cj2 s2 ON sid1 = sid2
ON t.tid = sid1 AND t.tid = 2
WHEN MATCHED THEN
        UPDATE SET src = src2
WHEN NOT MATCHED THEN
        DO NOTHING;
SELECT * FROM target_cj ORDER BY 1;
 tid |   src    | val
---------------------------------------------------------------------
   1 | target   |   0
   2 | source-2 |   0
   2 | source-2 |   0
   3 | target   |   0
(4 rows)

ROLLBACK;
BEGIN;
-- try accessing columns from either side of the source join
MERGE INTO target_cj t
USING source_cj1 s2
        INNER JOIN source_cj2 s1 ON sid1 = sid2 AND val1 = 10
ON t.tid = sid1 AND t.tid = 2
WHEN MATCHED THEN
        UPDATE SET src = src1, val = val2
WHEN NOT MATCHED THEN
        DO NOTHING;
SELECT * FROM target_cj ORDER BY 1;
 tid |   src    | val
---------------------------------------------------------------------
   1 | target   |   0
   2 | source-1 |  20
   2 | source-1 |  20
   3 | target   |   0
(4 rows)

ROLLBACK;
-- Test PREPARE
PREPARE insert(int, int, int) AS
MERGE INTO prept
USING (SELECT $2, s1, s2 FROM preps WHERE s2 > $3) as foo
ON prept.t1 = foo.s1
WHEN MATCHED THEN
        UPDATE SET t2 = t2 + $1
WHEN NOT MATCHED THEN
        INSERT VALUES(s1, s2);
PREPARE delete(int) AS
MERGE INTO prept
USING preps
ON prept.t1 = preps.s1
WHEN MATCHED AND prept.t2 = $1 THEN
        DELETE
WHEN MATCHED THEN
        UPDATE SET t2 = t2 + 1;
INSERT INTO prept VALUES(100, 0);
INSERT INTO preps VALUES(100, 0);
INSERT INTO preps VALUES(200, 0);
EXECUTE insert(1, 1, -1); EXECUTE delete(0);
EXECUTE insert(1, 1, -1); EXECUTE delete(0);
EXECUTE insert(1, 1, -1); EXECUTE delete(0);
EXECUTE insert(1, 1, -1); EXECUTE delete(0);
EXECUTE insert(1, 1, -1); EXECUTE delete(0);
-- sixth time
EXECUTE insert(1, 1, -1); EXECUTE delete(0);
EXECUTE insert(1, 1, -1); EXECUTE delete(0);
-- Should have the counter as 14 (7 * 2)
SELECT * FROM prept;
 t1  | t2
---------------------------------------------------------------------
 100 | 14
(1 row)

-- Test local tables
INSERT INTO s1 VALUES(1, 0); -- Matches DELETE clause
INSERT INTO s1 VALUES(2, 1); -- Matches UPDATE clause
INSERT INTO s1 VALUES(3, 1); -- No Match INSERT clause
INSERT INTO s1 VALUES(4, 1); -- No Match INSERT clause
INSERT INTO s1 VALUES(6, 1); -- No Match INSERT clause
INSERT INTO t1 VALUES(1, 0); -- Will be deleted
INSERT INTO t1 VALUES(2, 0); -- Will be updated
INSERT INTO t1 VALUES(5, 0); -- Will be intact
PREPARE local(int, int) AS
WITH s1_res AS (
        SELECT * FROM s1
)
MERGE INTO t1
        USING s1_res ON (s1_res.id = t1.id)
        WHEN MATCHED AND s1_res.val = $1 THEN
                DELETE
        WHEN MATCHED THEN
                UPDATE SET val = t1.val + $2
        WHEN NOT MATCHED THEN
                INSERT (id, val) VALUES (s1_res.id, s1_res.val);
BEGIN;
EXECUTE local(0, 1);
SELECT * FROM t1 order by id;
 id | val
---------------------------------------------------------------------
  2 |   1
  3 |   1
  4 |   1
  5 |   0
  6 |   1
(5 rows)

ROLLBACK;
BEGIN;
EXECUTE local(0, 1);
ROLLBACK;
BEGIN;
EXECUTE local(0, 1);
ROLLBACK;
BEGIN;
EXECUTE local(0, 1);
ROLLBACK;
BEGIN;
EXECUTE local(0, 1);
ROLLBACK;
-- sixth time
BEGIN;
EXECUTE local(0, 1);
ROLLBACK;
BEGIN;
EXECUTE local(0, 1);
SELECT * FROM t1 order by id;
 id | val
---------------------------------------------------------------------
  2 |   1
  3 |   1
  4 |   1
  5 |   0
  6 |   1
(5 rows)

ROLLBACK;
-- Test prepared statements with repartition
PREPARE merge_repartition_pg(int,int,int,int) as
        MERGE INTO pg_target target
        USING (SELECT id+1+$1 as key, val FROM (SELECT * FROM pg_source UNION SELECT * FROM pg_source WHERE id = $2) as foo) as source
        ON (source.key = target.id AND $3 < 10000)
        WHEN MATCHED THEN UPDATE SET val = (source.key::int+$4)
        WHEN NOT MATCHED THEN INSERT VALUES (source.key, source.val);
PREPARE merge_repartition_citus(int,int,int,int) as
        MERGE INTO citus_target target
        USING (SELECT id+1+$1 as key, val FROM (SELECT * FROM citus_source UNION SELECT * FROM citus_source WHERE id = $2) as foo) as source
        ON (source.key = target.id AND $3 < 10000)
        WHEN MATCHED THEN UPDATE SET val = (source.key::int+$4)
        WHEN NOT MATCHED THEN INSERT VALUES (source.key, source.val);
EXECUTE merge_repartition_pg(1,1,1,1);
EXECUTE merge_repartition_citus(1,1,1,1);
SET client_min_messages = NOTICE;
SELECT compare_data();
NOTICE:  The average of pg_target.id is equal to citus_target.id
NOTICE:  The average of pg_target.val is equal to citus_target.val
 compare_data
---------------------------------------------------------------------

(1 row)

RESET client_min_messages;
EXECUTE merge_repartition_pg(1,100,1,1);
EXECUTE merge_repartition_citus(1,100,1,1);
EXECUTE merge_repartition_pg(2,200,1,1);
EXECUTE merge_repartition_citus(2,200,1,1);
EXECUTE merge_repartition_pg(3,300,1,1);
EXECUTE merge_repartition_citus(3,300,1,1);
EXECUTE merge_repartition_pg(4,400,1,1);
EXECUTE merge_repartition_citus(4,400,1,1);
EXECUTE merge_repartition_pg(5,500,1,1);
EXECUTE merge_repartition_citus(5,500,1,1);
-- Sixth time
EXECUTE merge_repartition_pg(6,600,1,6);
EXECUTE merge_repartition_citus(6,600,1,6);
SET client_min_messages = NOTICE;
SELECT compare_data();
NOTICE:  The average of pg_target.id is equal to citus_target.id
NOTICE:  The average of pg_target.val is equal to citus_target.val
 compare_data
---------------------------------------------------------------------

(1 row)

RESET client_min_messages;
