--
-- join with subquery pushdown support
--
SET citus.next_shard_id TO 9000000;
CREATE SCHEMA join_schema;
SET search_path TO join_schema, public;
CREATE TABLE test_table_1(id int, val1 int);
CREATE TABLE test_table_2(id bigint, val1 int);
CREATE TABLE test_table_3(id int, val1 bigint);
CREATE TABLE abcd(a int, b int, c int, d int);
CREATE TABLE distributed_table(a int, b int);
CREATE TABLE reference_table(a int, c int, b int);
SELECT create_distributed_table('distributed_table', 'a');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

SELECT create_reference_table('reference_table');
 create_reference_table
---------------------------------------------------------------------

(1 row)

SELECT create_distributed_table('test_table_1', 'id');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

SELECT create_distributed_table('test_table_2', 'id');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

SELECT create_distributed_table('test_table_3', 'id');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

SELECT create_distributed_table('abcd', 'b');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

INSERT INTO test_table_1 VALUES(1,1),(2,2),(3,3);
INSERT INTO test_table_2 VALUES(2,2),(3,3),(4,4);
INSERT INTO test_table_3 VALUES(1,1),(3,3),(4,5);
-- Simple full outer join
SELECT id FROM test_table_1 FULL JOIN test_table_3 using(id) ORDER BY 1;
 id
---------------------------------------------------------------------
  1
  2
  3
  4
(4 rows)

-- Get all columns as the result of the full join
SELECT * FROM test_table_1 FULL JOIN test_table_3 using(id) ORDER BY 1;
 id | val1 | val1
---------------------------------------------------------------------
  1 |    1 |    1
  2 |    2 |
  3 |    3 |    3
  4 |      |    5
(4 rows)

-- Join subqueries using single column
SELECT * FROM
	(SELECT test_table_1.id FROM test_table_1 FULL JOIN test_table_3 using(id)) as j1
		FULL JOIN
	(SELECT test_table_1.id FROM test_table_1 FULL JOIN test_table_3 using(id)) as j2
	USING(id)
	ORDER BY 1;
 id
---------------------------------------------------------------------
  1
  2
  3


(5 rows)

-- Join subqueries using multiple columns
SELECT * FROM
	(SELECT test_table_1.id, test_table_1.val1 FROM test_table_1 FULL JOIN test_table_3 using(id)) as j1
		FULL JOIN
	(SELECT test_table_1.id, test_table_1.val1 FROM test_table_1 FULL JOIN test_table_3 using(id)) as j2
	USING(id, val1)
	ORDER BY 1;
 id | val1
---------------------------------------------------------------------
  1 |    1
  2 |    2
  3 |    3
    |
    |
(5 rows)

-- Full join using multiple columns
SELECT * FROM test_table_1 FULL JOIN test_table_3 USING(id, val1) ORDER BY 1;
 id | val1
---------------------------------------------------------------------
  1 |    1
  2 |    2
  3 |    3
  4 |    5
(4 rows)

-- Full join with complicated target lists
SELECT count(DISTINCT id), (avg(test_table_1.val1) + id * id)::integer as avg_value, id::numeric IS NOT NULL as not_null
FROM test_table_1 FULL JOIN test_table_3 using(id)
WHERE id::bigint < 55
GROUP BY id
ORDER BY 2
ASC LIMIT 3;
 count | avg_value | not_null
---------------------------------------------------------------------
     1 |         2 | t
     1 |         6 | t
     1 |        12 | t
(3 rows)

SELECT max(val1)
FROM test_table_1 FULL JOIN test_table_3 USING(id, val1)
GROUP BY test_table_1.id
ORDER BY 1;
 max
---------------------------------------------------------------------
   1
   2
   3
   5
(4 rows)

-- Test the left join as well
SELECT max(val1)
FROM test_table_1 LEFT JOIN test_table_3 USING(id, val1)
GROUP BY test_table_1.id
ORDER BY 1;
 max
---------------------------------------------------------------------
   1
   2
   3
(3 rows)

-- Full outer join with different distribution column types, should error out
SELECT * FROM test_table_1 full join test_table_2 using(id);
ERROR:  cannot push down this subquery
DETAIL:  test_table_1 and test_table_2 are not colocated
-- Test when the non-distributed column has the value of NULL
INSERT INTO test_table_1 VALUES(7, NULL);
INSERT INTO test_table_2 VALUES(7, NULL);
INSERT INTO test_table_3 VALUES(7, NULL);
-- Get all columns as the result of the full join
SELECT * FROM test_table_1 FULL JOIN test_table_3 using(id) ORDER BY 1;
 id | val1 | val1
---------------------------------------------------------------------
  1 |    1 |    1
  2 |    2 |
  3 |    3 |    3
  4 |      |    5
  7 |      |
(5 rows)

-- Get the same result (with multiple id)
SELECT * FROM test_table_1 FULL JOIN test_table_3 ON (test_table_1.id = test_table_3.id) ORDER BY 1;
 id | val1 | id | val1
---------------------------------------------------------------------
  1 |    1 |  1 |    1
  2 |    2 |    |
  3 |    3 |  3 |    3
  7 |      |  7 |
    |      |  4 |    5
(5 rows)

-- Full join using multiple columns
SELECT * FROM test_table_1 FULL JOIN test_table_3 USING(id, val1) ORDER BY 1;
 id | val1
---------------------------------------------------------------------
  1 |    1
  2 |    2
  3 |    3
  4 |    5
  7 |
  7 |
(6 rows)

-- In order to make the same test with different data types use text-varchar pair
-- instead of using int-bigint pair.
DROP TABLE test_table_1;
DROP TABLE test_table_2;
DROP TABLE test_table_3;
CREATE TABLE test_table_1(id int, val1 text);
CREATE TABLE test_table_2(id int, val1 varchar(30));
SELECT create_distributed_table('test_table_1', 'id');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

SELECT create_distributed_table('test_table_2', 'id');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

INSERT INTO test_table_1 VALUES(1,'val_1'),(2,'val_2'),(3,'val_3'), (4, NULL);
INSERT INTO test_table_2 VALUES(2,'val_2'),(3,'val_3'),(4,'val_4'), (5, NULL);
-- Simple full outer join
SELECT id FROM test_table_1 FULL JOIN test_table_2 using(id) ORDER BY 1;
 id
---------------------------------------------------------------------
  1
  2
  3
  4
  5
(5 rows)

-- Get all columns as the result of the full join
SELECT * FROM test_table_1 FULL JOIN test_table_2 using(id) ORDER BY 1;
 id | val1  | val1
---------------------------------------------------------------------
  1 | val_1 |
  2 | val_2 | val_2
  3 | val_3 | val_3
  4 |       | val_4
  5 |       |
(5 rows)

-- Join subqueries using multiple columns
SELECT * FROM
	(SELECT test_table_1.id, test_table_1.val1 FROM test_table_1 FULL JOIN test_table_2 using(id)) as j1
		FULL JOIN
	(SELECT test_table_2.id, test_table_2.val1 FROM test_table_1 FULL JOIN test_table_2 using(id)) as j2
	USING(id, val1)
	ORDER BY 1,2;
 id | val1
---------------------------------------------------------------------
  1 | val_1
  2 | val_2
  3 | val_3
  4 | val_4
  4 |
  5 |
    |
    |
(8 rows)

-- Full join using multiple columns
SELECT * FROM test_table_1 FULL JOIN test_table_2 USING(id, val1) ORDER BY 1,2;
 id | val1
---------------------------------------------------------------------
  1 | val_1
  2 | val_2
  3 | val_3
  4 | val_4
  4 |
  5 |
(6 rows)

SET citus.enable_repartition_joins to ON;
SELECT distributed_table.* from distributed_table JOIN reference_table ON (true);
 a | b
---------------------------------------------------------------------
(0 rows)

ALTER TABLE reference_table DROP COLUMN c;
-- #4129: make sure a join after drop column works
SELECT distributed_table.* from distributed_table JOIN reference_table ON (true);
 a | b
---------------------------------------------------------------------
(0 rows)

BEGIN;
SELECT distributed_table.* from distributed_table JOIN reference_table ON (true);
 a | b
---------------------------------------------------------------------
(0 rows)

END;
INSERT INTO abcd VALUES (1,2,3,4);
INSERT INTO abcd VALUES (2,3,4,5);
INSERT INTO abcd VALUES (3,4,5,6);
SELECT * FROM abcd first join abcd second on first.a = second.a ORDER BY 1,2,3,4;
 a | b | c | d | a | b | c | d
---------------------------------------------------------------------
 1 | 2 | 3 | 4 | 1 | 2 | 3 | 4
 2 | 3 | 4 | 5 | 2 | 3 | 4 | 5
 3 | 4 | 5 | 6 | 3 | 4 | 5 | 6
(3 rows)

SELECT * FROM abcd first join abcd second on first.b = second.b ORDER BY 1,2,3,4;
 a | b | c | d | a | b | c | d
---------------------------------------------------------------------
 1 | 2 | 3 | 4 | 1 | 2 | 3 | 4
 2 | 3 | 4 | 5 | 2 | 3 | 4 | 5
 3 | 4 | 5 | 6 | 3 | 4 | 5 | 6
(3 rows)

SELECT * FROM abcd first join abcd second on first.c = second.c ORDER BY 1,2,3,4;
 a | b | c | d | a | b | c | d
---------------------------------------------------------------------
 1 | 2 | 3 | 4 | 1 | 2 | 3 | 4
 2 | 3 | 4 | 5 | 2 | 3 | 4 | 5
 3 | 4 | 5 | 6 | 3 | 4 | 5 | 6
(3 rows)

BEGIN;
SELECT * FROM abcd first join abcd second on first.a = second.a ORDER BY 1,2,3,4;
 a | b | c | d | a | b | c | d
---------------------------------------------------------------------
 1 | 2 | 3 | 4 | 1 | 2 | 3 | 4
 2 | 3 | 4 | 5 | 2 | 3 | 4 | 5
 3 | 4 | 5 | 6 | 3 | 4 | 5 | 6
(3 rows)

SELECT * FROM abcd first join abcd second on first.b = second.b ORDER BY 1,2,3,4;
 a | b | c | d | a | b | c | d
---------------------------------------------------------------------
 1 | 2 | 3 | 4 | 1 | 2 | 3 | 4
 2 | 3 | 4 | 5 | 2 | 3 | 4 | 5
 3 | 4 | 5 | 6 | 3 | 4 | 5 | 6
(3 rows)

SELECT * FROM abcd first join abcd second on first.c = second.c ORDER BY 1,2,3,4;
 a | b | c | d | a | b | c | d
---------------------------------------------------------------------
 1 | 2 | 3 | 4 | 1 | 2 | 3 | 4
 2 | 3 | 4 | 5 | 2 | 3 | 4 | 5
 3 | 4 | 5 | 6 | 3 | 4 | 5 | 6
(3 rows)

END;
ALTER TABLE abcd DROP COLUMN a;
SELECT * FROM abcd first join abcd second on first.b = second.b ORDER BY 1,2,3,4;
 b | c | d | b | c | d
---------------------------------------------------------------------
 2 | 3 | 4 | 2 | 3 | 4
 3 | 4 | 5 | 3 | 4 | 5
 4 | 5 | 6 | 4 | 5 | 6
(3 rows)

SELECT * FROM abcd first join abcd second on first.c = second.c ORDER BY 1,2,3,4;
 b | c | d | b | c | d
---------------------------------------------------------------------
 2 | 3 | 4 | 2 | 3 | 4
 3 | 4 | 5 | 3 | 4 | 5
 4 | 5 | 6 | 4 | 5 | 6
(3 rows)

BEGIN;
SELECT * FROM abcd first join abcd second on first.b = second.b ORDER BY 1,2,3,4;
 b | c | d | b | c | d
---------------------------------------------------------------------
 2 | 3 | 4 | 2 | 3 | 4
 3 | 4 | 5 | 3 | 4 | 5
 4 | 5 | 6 | 4 | 5 | 6
(3 rows)

SELECT * FROM abcd first join abcd second on first.c = second.c ORDER BY 1,2,3,4;
 b | c | d | b | c | d
---------------------------------------------------------------------
 2 | 3 | 4 | 2 | 3 | 4
 3 | 4 | 5 | 3 | 4 | 5
 4 | 5 | 6 | 4 | 5 | 6
(3 rows)

END;
CREATE VIEW abcd_view AS SELECT * FROM abcd;
SELECT * FROM abcd_view first join abcd_view second on first.b = second.b ORDER BY 1,2,3,4;
 b | c | d | b | c | d
---------------------------------------------------------------------
 2 | 3 | 4 | 2 | 3 | 4
 3 | 4 | 5 | 3 | 4 | 5
 4 | 5 | 6 | 4 | 5 | 6
(3 rows)

SELECT * FROM abcd_view first join abcd_view second on first.c = second.c ORDER BY 1,2,3,4;
 b | c | d | b | c | d
---------------------------------------------------------------------
 2 | 3 | 4 | 2 | 3 | 4
 3 | 4 | 5 | 3 | 4 | 5
 4 | 5 | 6 | 4 | 5 | 6
(3 rows)

BEGIN;
SELECT * FROM abcd_view first join abcd_view second on first.b = second.b ORDER BY 1,2,3,4;
 b | c | d | b | c | d
---------------------------------------------------------------------
 2 | 3 | 4 | 2 | 3 | 4
 3 | 4 | 5 | 3 | 4 | 5
 4 | 5 | 6 | 4 | 5 | 6
(3 rows)

SELECT * FROM abcd_view first join abcd_view second on first.c = second.c ORDER BY 1,2,3,4;
 b | c | d | b | c | d
---------------------------------------------------------------------
 2 | 3 | 4 | 2 | 3 | 4
 3 | 4 | 5 | 3 | 4 | 5
 4 | 5 | 6 | 4 | 5 | 6
(3 rows)

END;
SELECT * FROM abcd first full join abcd second on first.b = second.b ORDER BY 1,2,3,4;
 b | c | d | b | c | d
---------------------------------------------------------------------
 2 | 3 | 4 | 2 | 3 | 4
 3 | 4 | 5 | 3 | 4 | 5
 4 | 5 | 6 | 4 | 5 | 6
(3 rows)

BEGIN;
SELECT * FROM abcd first full join abcd second on first.b = second.b ORDER BY 1,2,3,4;
 b | c | d | b | c | d
---------------------------------------------------------------------
 2 | 3 | 4 | 2 | 3 | 4
 3 | 4 | 5 | 3 | 4 | 5
 4 | 5 | 6 | 4 | 5 | 6
(3 rows)

END;
SELECT * FROM abcd_view first join abcd second USING(b) ORDER BY 1,2,3,4;
 b | c | d | c | d
---------------------------------------------------------------------
 2 | 3 | 4 | 3 | 4
 3 | 4 | 5 | 4 | 5
 4 | 5 | 6 | 5 | 6
(3 rows)

BEGIN;
SELECT * FROM abcd first join abcd second USING(b) ORDER BY 1,2,3,4;
 b | c | d | c | d
---------------------------------------------------------------------
 2 | 3 | 4 | 3 | 4
 3 | 4 | 5 | 4 | 5
 4 | 5 | 6 | 5 | 6
(3 rows)

END;
SELECT * FROM abcd first join abcd second USING(b) join abcd third on first.b=third.b ORDER BY 1,2,3,4;
 b | c | d | c | d | b | c | d
---------------------------------------------------------------------
 2 | 3 | 4 | 3 | 4 | 2 | 3 | 4
 3 | 4 | 5 | 4 | 5 | 3 | 4 | 5
 4 | 5 | 6 | 5 | 6 | 4 | 5 | 6
(3 rows)

BEGIN;
SELECT * FROM abcd first join abcd second USING(b) join abcd third on first.b=third.b ORDER BY 1,2,3,4;
 b | c | d | c | d | b | c | d
---------------------------------------------------------------------
 2 | 3 | 4 | 3 | 4 | 2 | 3 | 4
 3 | 4 | 5 | 4 | 5 | 3 | 4 | 5
 4 | 5 | 6 | 5 | 6 | 4 | 5 | 6
(3 rows)

END;
DROP SCHEMA join_schema CASCADE;
NOTICE:  drop cascades to 7 other objects
DETAIL:  drop cascades to table abcd
drop cascades to table distributed_table
drop cascades to table reference_table
drop cascades to table reference_table_9000004
drop cascades to table test_table_1
drop cascades to table test_table_2
drop cascades to view abcd_view
