--
-- MULTI_SUBQUERY
--
-- no need to set shardid sequence given that we're not creating any shards
SET citus.next_shard_id TO 570032;
SET citus.coordinator_aggregation_strategy TO 'disabled';
-- Check that we error out if shard min/max values are not exactly same.
SELECT
	avg(unit_price)
FROM
	(SELECT
		l_orderkey,
		avg(o_totalprice) AS unit_price
	FROM
		lineitem_subquery,
		orders_subquery
	WHERE
		l_orderkey = o_orderkey
	GROUP BY
		l_orderkey) AS unit_prices;
           avg
---------------------------------------------------------------------
 142158.8766934673366834
(1 row)

-- Update metadata in order to make all shards equal
-- note that the table is created on multi_insert_select_create_table.sql
UPDATE
	pg_dist_shard
SET
	shardmaxvalue = '14947'
WHERE
	shardid IN (SELECT shardid FROM pg_dist_shard WHERE logicalrelid = 'orders_subquery'::regclass ORDER BY shardid DESC LIMIT 1);
SET client_min_messages TO DEBUG1;
-- If group by is not on partition column then we recursively plan
SELECT
	avg(order_count)
FROM
	(SELECT
		l_suppkey,
		count(*) AS order_count
	FROM
		lineitem_subquery
	GROUP BY
		l_suppkey) AS order_counts;
DEBUG:  generating subplan XXX_1 for subquery SELECT l_suppkey, count(*) AS order_count FROM public.lineitem_subquery GROUP BY l_suppkey
DEBUG:  Plan XXX query after replacing subqueries and CTEs: SELECT avg(order_count) AS avg FROM (SELECT intermediate_result.l_suppkey, intermediate_result.order_count FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(l_suppkey integer, order_count bigint)) order_counts
        avg
---------------------------------------------------------------------
 1.7199369356456930
(1 row)

-- Check that we recursively plan if join is not on partition columns.
SELECT
	avg(unit_price)
FROM
	(SELECT
		l_orderkey,
		avg(o_totalprice / l_quantity) AS unit_price
	FROM
		lineitem_subquery,
		orders_subquery
	GROUP BY
		l_orderkey) AS unit_prices;
ERROR:  cannot perform distributed planning on this query
DETAIL:  Cartesian products are currently unsupported
RESET client_min_messages;
-- Subqueries without relation with a volatile functions (non-constant) are planned recursively
SELECT count(*) FROM (
   SELECT l_orderkey FROM lineitem_subquery JOIN (SELECT random()::int r) sub ON (l_orderkey = r) WHERE r > 10
) b;
 count
---------------------------------------------------------------------
     0
(1 row)

SET client_min_messages TO DEBUG;
-- If there is non relation subqueries then we recursively plan
SELECT count(*) FROM
(
   (SELECT l_orderkey FROM lineitem_subquery) UNION ALL
   (SELECT 1::bigint)
) b;
DEBUG:  Router planner cannot handle multi-shard select queries
DEBUG:  Router planner cannot handle multi-shard select queries
DEBUG:  generating subplan XXX_1 for subquery SELECT l_orderkey FROM public.lineitem_subquery
DEBUG:  Creating router plan
DEBUG:  Plan is router executable
DEBUG:  generating subplan XXX_2 for subquery SELECT intermediate_result.l_orderkey FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(l_orderkey bigint) UNION ALL SELECT (1)::bigint AS int8
DEBUG:  Plan XXX query after replacing subqueries and CTEs: SELECT count(*) AS count FROM (SELECT intermediate_result.l_orderkey FROM read_intermediate_result('XXX_2'::text, 'binary'::citus_copy_format) intermediate_result(l_orderkey bigint)) b
DEBUG:  Creating router plan
DEBUG:  Plan is router executable
 count
---------------------------------------------------------------------
 12001
(1 row)

-- If queries in union do not include partition columns then we recursively plan
SELECT count(*) FROM
(
   (SELECT l_orderkey FROM lineitem_subquery) UNION
   (SELECT l_partkey FROM lineitem_subquery)
) b;
DEBUG:  Router planner cannot handle multi-shard select queries
DEBUG:  Router planner cannot handle multi-shard select queries
DEBUG:  generating subplan XXX_1 for subquery SELECT l_orderkey FROM public.lineitem_subquery
DEBUG:  Router planner cannot handle multi-shard select queries
DEBUG:  generating subplan XXX_2 for subquery SELECT l_partkey FROM public.lineitem_subquery
DEBUG:  Creating router plan
DEBUG:  Plan is router executable
DEBUG:  generating subplan XXX_3 for subquery SELECT intermediate_result.l_orderkey FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(l_orderkey bigint) UNION SELECT intermediate_result.l_partkey FROM read_intermediate_result('XXX_2'::text, 'binary'::citus_copy_format) intermediate_result(l_partkey integer)
DEBUG:  Plan XXX query after replacing subqueries and CTEs: SELECT count(*) AS count FROM (SELECT intermediate_result.l_orderkey FROM read_intermediate_result('XXX_3'::text, 'binary'::citus_copy_format) intermediate_result(l_orderkey bigint)) b
DEBUG:  Creating router plan
DEBUG:  Plan is router executable
 count
---------------------------------------------------------------------
 14496
(1 row)

-- Check that we push down union queries if partition column is selected (no DEBUG messages)
SELECT count(*) FROM
(
   (SELECT l_orderkey FROM lineitem_subquery) UNION
   (SELECT l_orderkey FROM lineitem_subquery)
) b;
DEBUG:  Router planner cannot handle multi-shard select queries
 count
---------------------------------------------------------------------
  2985
(1 row)

RESET client_min_messages;
-- we'd error out if inner query has Limit but subquery_pushdown is not set
-- but we recursively plan the query
SELECT
	avg(o_totalprice/l_quantity)
FROM
		(SELECT
			l_orderkey,
			l_quantity
		FROM
			lineitem_subquery
		ORDER BY
			l_orderkey, l_quantity
		LIMIT 10
		) lineitem_quantities
	JOIN LATERAL
		(SELECT
			o_totalprice
		FROM
			orders_subquery
		WHERE
			lineitem_quantities.l_orderkey = o_orderkey) orders_price ON true;
          avg
---------------------------------------------------------------------
 17470.0940725222668915
(1 row)

-- Limit is only supported when subquery_pushdown is set
-- Check that we error out if inner query has limit but outer query has not.
SET citus.subquery_pushdown to ON;
SELECT
	avg(o_totalprice/l_quantity)
FROM
		(SELECT
			l_orderkey,
			l_quantity
		FROM
			lineitem_subquery
		ORDER BY
			l_orderkey, l_quantity
		LIMIT 10
		) lineitem_quantities
	JOIN LATERAL
		(SELECT
			o_totalprice
		FROM
			orders_subquery
		WHERE
			lineitem_quantities.l_orderkey = o_orderkey) orders_price ON true;
ERROR:  cannot push down this subquery
DETAIL:  Limit in subquery without limit in the outermost query is unsupported
-- reset the flag for next query
SET citus.subquery_pushdown to OFF;
-- some queries without a subquery uses subquery planner
SELECT l_orderkey
FROM
	lineitem_subquery l
JOIN
	orders_subquery o
ON (l_orderkey = o_orderkey)
WHERE
	(o_orderkey < l_quantity)
ORDER BY l_orderkey DESC
LIMIT 10;
 l_orderkey
---------------------------------------------------------------------
         39
         39
         39
         39
         38
         37
         37
         37
         36
         33
(10 rows)

-- query is still supported if contains additional join
-- clauses that includes arithmetic expressions
SELECT l_orderkey
FROM
	lineitem_subquery l
JOIN
	orders_subquery o
ON (l_orderkey = o_orderkey)
WHERE
	(o_orderkey < l_quantity + 3)
ORDER BY l_orderkey DESC
LIMIT 10;
 l_orderkey
---------------------------------------------------------------------
         39
         39
         39
         39
         38
         37
         37
         37
         36
         35
(10 rows)

-- implicit typecasts in joins is supported
SELECT l_orderkey
FROM
	lineitem_subquery l
JOIN
	orders_subquery o
ON (l_orderkey::int8 = o_orderkey::int8)
WHERE
	(o_orderkey < l_quantity + 3)
ORDER BY l_orderkey DESC
LIMIT 10;
 l_orderkey
---------------------------------------------------------------------
         39
         39
         39
         39
         38
         37
         37
         37
         36
         35
(10 rows)

-- non-implicit typecasts in joins is not supported
SELECT l_orderkey
FROM
	lineitem_subquery l
JOIN
	orders_subquery o
ON (l_orderkey::int8 = o_orderkey::int4)
WHERE
	(o_orderkey < l_quantity + 3)
ORDER BY l_orderkey DESC
LIMIT 10;
ERROR:  complex joins are only supported when all distributed tables are joined on their distribution columns with equal operator
-- implicit typecast supported in equi-join
SELECT l_orderkey
FROM
	lineitem_subquery l
JOIN
	orders_subquery o
ON (l_orderkey::int8 = o_orderkey::int8)
ORDER BY l_orderkey DESC
LIMIT 10;
 l_orderkey
---------------------------------------------------------------------
      14947
      14947
      14946
      14946
      14945
      14945
      14945
      14945
      14945
      14945
(10 rows)

-- non-implicit typecast is not supported in equi-join
SELECT l_orderkey
FROM
	lineitem_subquery l
JOIN
	orders_subquery o
ON (l_orderkey::int4 = o_orderkey::int8)
ORDER BY l_orderkey DESC
LIMIT 10;
ERROR:  complex joins are only supported when all distributed tables are joined on their distribution columns with equal operator
-- type casts in filters are supported as long as
-- a valid equi-join exists
SELECT l_orderkey
FROM
	lineitem_subquery l
JOIN
	orders_subquery o
ON (l_orderkey = o_orderkey)
WHERE
	(o_orderkey::int8 < l_quantity::int8 + 3)
ORDER BY l_orderkey DESC
LIMIT 10;
 l_orderkey
---------------------------------------------------------------------
         39
         39
         39
         39
         38
         37
         37
         37
         36
         35
(10 rows)

-- even if type cast is non-implicit
SELECT l_orderkey
FROM
	lineitem_subquery l
JOIN
	orders_subquery o
ON (l_orderkey = o_orderkey)
WHERE
	(o_orderkey::int4 < l_quantity::int8 + 3)
ORDER BY l_orderkey DESC
LIMIT 10;
 l_orderkey
---------------------------------------------------------------------
         39
         39
         39
         39
         38
         37
         37
         37
         36
         35
(10 rows)

-- query is not supported if contains an partition column
-- equi join that includes arithmetic expressions
SELECT l_orderkey
FROM
	lineitem_subquery l
JOIN
	orders_subquery o
ON (l_orderkey = o_orderkey + 1)
WHERE
	(o_orderkey < l_quantity)
ORDER BY l_orderkey DESC
LIMIT 10;
ERROR:  complex joins are only supported when all distributed tables are joined on their distribution columns with equal operator
-- query is not supported if there is a single
-- join clause with arithmetic expression. It fails
-- with a different error message
SELECT l_orderkey
FROM
	lineitem_subquery l
JOIN
	orders_subquery o
ON (l_orderkey = o_orderkey + 1)
ORDER BY l_orderkey DESC
LIMIT 10;
ERROR:  complex joins are only supported when all distributed tables are joined on their distribution columns with equal operator
-- query is not supported if does not have equi-join clause
SELECT l_orderkey
FROM
	lineitem_subquery l
JOIN
	orders_subquery o
ON (l_orderkey < o_orderkey)
WHERE
	(o_orderkey < l_quantity)
ORDER BY l_orderkey DESC
LIMIT 10;
ERROR:  complex joins are only supported when all distributed tables are joined on their distribution columns with equal operator
-- outer joins on reference tables with functions works
SELECT DISTINCT ON (t1.user_id) t1.user_id, t2.value_1, t2.value_2, t2.value_3
FROM events_table t1
LEFT JOIN users_reference_table t2 ON t1.user_id = trunc(t2.user_id)
ORDER BY 1 DESC, 2 DESC, 3 DESC, 4 DESC
LIMIT 5;
 user_id | value_1 | value_2 | value_3
---------------------------------------------------------------------
       6 |       5 |       2 |       0
       5 |       5 |       5 |       1
       4 |       5 |       4 |       1
       3 |       5 |       5 |       3
       2 |       4 |       4 |       5
(5 rows)

-- outer joins on reference tables with simple expressions should work
SELECT DISTINCT ON (t1.user_id) t1.user_id, t2.value_1, t2.value_2, t2.value_3
FROM events_table t1
LEFT JOIN users_reference_table t2 ON t1.user_id > t2.user_id
ORDER BY 1 DESC, 2 DESC, 3 DESC, 4 DESC
LIMIT 5;
 user_id | value_1 | value_2 | value_3
---------------------------------------------------------------------
       6 |       5 |       5 |       3
       5 |       5 |       5 |       3
       4 |       5 |       5 |       3
       3 |       5 |       4 |       3
       2 |       5 |       4 |       3
(5 rows)

-- outer joins on distributed tables with simple expressions should not work
SELECT DISTINCT ON (t1.user_id) t1.user_id, t2.value_1, t2.value_2, t2.value_3
FROM events_table t1
LEFT JOIN users_table t2 ON t1.user_id > t2.user_id
ORDER BY 1 DESC, 2 DESC, 3 DESC, 4 DESC
LIMIT 5;
ERROR:  complex joins are only supported when all distributed tables are co-located and joined on their distribution columns
-- outer joins on reference tables with expressions should work
SELECT DISTINCT ON (t1.user_id) t1.user_id, t2.value_1, t2.value_2, t2.value_3
FROM events_table t1
LEFT JOIN users_reference_table t2 ON t1.user_id = (CASE WHEN t2.user_id > 3 THEN 3 ELSE t2.user_id END)
ORDER BY 1 DESC, 2 DESC, 3 DESC, 4 DESC
LIMIT 5;
 user_id | value_1 | value_2 | value_3
---------------------------------------------------------------------
       6 |         |         |
       5 |         |         |
       4 |         |         |
       3 |       5 |       5 |       3
       2 |       4 |       4 |       5
(5 rows)

-- outer joins on distributed tables and reference tables with expressions should work
SELECT DISTINCT ON (t1.user_id) t1.user_id, t2.value_1, t2.value_2, t2.value_3
 FROM
 users_table t0 LEFT JOIN
 events_table t1  ON t0.user_id = t1.user_id
 LEFT JOIN users_reference_table t2 ON t1.user_id = trunc(t2.user_id)
 ORDER BY 1 DESC, 2 DESC, 3 DESC, 4 DESC
 LIMIT 5;
 user_id | value_1 | value_2 | value_3
---------------------------------------------------------------------
       6 |       5 |       2 |       0
       5 |       5 |       5 |       1
       4 |       5 |       4 |       1
       3 |       5 |       5 |       3
       2 |       4 |       4 |       5
(5 rows)

-- outer joins on distributed tables with expressions should not work
SELECT DISTINCT ON (t1.user_id) t1.user_id, t2.value_1, t2.value_2, t2.value_3
 FROM
 users_table t0 LEFT JOIN
 events_table t1  ON t0.user_id = trunc(t1.user_id)
 LEFT JOIN users_reference_table t2 ON t1.user_id = trunc(t2.user_id)
 ORDER BY 1 DESC, 2 DESC, 3 DESC, 4 DESC
 LIMIT 5;
ERROR:  complex joins are only supported when all distributed tables are co-located and joined on their distribution columns
-- outer joins as subqueries should work
-- https://github.com/citusdata/citus/issues/2739
SELECT user_id, value_1, event_type
FROM (
	SELECT a.user_id, a.value_1, b.event_type
	FROM users_table a
	LEFT JOIN events_table b ON a.user_id = b.user_id
) lo
ORDER BY 1, 2, 3
LIMIT 5;
 user_id | value_1 | event_type
---------------------------------------------------------------------
       1 |       1 |          0
       1 |       1 |          0
       1 |       1 |          1
       1 |       1 |          1
       1 |       1 |          2
(5 rows)

-- inner joins on reference tables with functions works
SELECT DISTINCT ON (t1.user_id) t1.user_id, t2.value_1, t2.value_2, t2.value_3
FROM events_table t1
JOIN users_reference_table t2 ON t1.user_id = trunc(t2.user_id)
ORDER BY 1 DESC, 2 DESC, 3 DESC, 4 DESC
LIMIT 5;
 user_id | value_1 | value_2 | value_3
---------------------------------------------------------------------
       6 |       5 |       2 |       0
       5 |       5 |       5 |       1
       4 |       5 |       4 |       1
       3 |       5 |       5 |       3
       2 |       4 |       4 |       5
(5 rows)

-- distinct queries work
SELECT DISTINCT l_orderkey
FROM
	lineitem_subquery l
JOIN
	orders_subquery o
ON (l_orderkey = o_orderkey)
WHERE
	(o_orderkey < l_quantity)
ORDER BY l_orderkey DESC
LIMIT 10;
 l_orderkey
---------------------------------------------------------------------
         39
         38
         37
         36
         33
         32
          7
          6
          5
          4
(10 rows)

-- count(distinct) queries work
SELECT COUNT(DISTINCT l_orderkey)
FROM
	lineitem_subquery l
JOIN
	orders_subquery o
ON (l_orderkey = o_orderkey)
WHERE
	(o_orderkey < l_quantity);
 count
---------------------------------------------------------------------
    13
(1 row)

-- the same queries returning a non-partition column
SELECT l_quantity
FROM
	lineitem_subquery l
JOIN
	orders_subquery o
ON (l_orderkey = o_orderkey)
WHERE
	(o_orderkey < l_quantity)
ORDER BY l_quantity DESC
LIMIT 10;
 l_quantity
---------------------------------------------------------------------
      50.00
      49.00
      46.00
      46.00
      45.00
      44.00
      44.00
      44.00
      43.00
      43.00
(10 rows)

-- distinct queries work
SELECT DISTINCT l_quantity
FROM
	lineitem_subquery l
JOIN
	orders_subquery o
ON (l_orderkey = o_orderkey)
WHERE
	(o_orderkey < l_quantity)
ORDER BY l_quantity DESC
LIMIT 10;
 l_quantity
---------------------------------------------------------------------
      50.00
      49.00
      46.00
      45.00
      44.00
      43.00
      42.00
      41.00
      40.00
      39.00
(10 rows)

-- count(distinct) queries work
SELECT COUNT(DISTINCT l_quantity)
FROM
	lineitem_subquery l
JOIN
	orders_subquery o
ON (l_orderkey = o_orderkey)
WHERE
	(o_orderkey < l_quantity);
 count
---------------------------------------------------------------------
    25
(1 row)

-- Check that we support count distinct with a subquery
SELECT
	count(DISTINCT a)
FROM (
	SELECT
		count(*) a
	FROM
		lineitem_subquery
	GROUP BY
	   l_orderkey
) z;
 count
---------------------------------------------------------------------
     7
(1 row)

-- We do not support distinct aggregates other than count distinct with a subquery
SELECT
	sum(DISTINCT a)
FROM (
	SELECT
		count(*) a
	FROM
		lineitem_subquery
	GROUP BY
	   l_orderkey
) z;
ERROR:  cannot compute aggregate (distinct)
DETAIL:  Only count(distinct) aggregate is supported in subqueries
SELECT
	avg(DISTINCT a)
FROM (
	SELECT
		count(*) a
	FROM
		lineitem_subquery
	GROUP BY
	   l_orderkey
) z;
ERROR:  cannot compute aggregate (distinct)
DETAIL:  Only count(distinct) aggregate is supported in subqueries
-- Check supported subquery types.
SELECT
	o_custkey,
	sum(order_count) as total_order_count
FROM
	(SELECT
		o_orderkey,
		o_custkey,
		count(*) AS order_count
	FROM
		orders_subquery
	WHERE
		o_orderkey > 0 AND
		o_orderkey < 12000
	GROUP BY
		o_orderkey, o_custkey) AS order_counts
GROUP BY
	o_custkey
ORDER BY
	total_order_count DESC,
	o_custkey ASC
LIMIT 10;
 o_custkey | total_order_count
---------------------------------------------------------------------
      1462 |                 9
       619 |                 8
       643 |                 8
      1030 |                 8
      1486 |                 8
        79 |                 7
       304 |                 7
       319 |                 7
       343 |                 7
       448 |                 7
(10 rows)

SELECT
	avg(unit_price)
FROM
	(SELECT
		l_orderkey,
		avg(o_totalprice / l_quantity) AS unit_price
	FROM
		lineitem_subquery,
		orders_subquery
	WHERE
		l_orderkey = o_orderkey
	GROUP BY
		l_orderkey) AS unit_prices
WHERE
	unit_price > 1000 AND
	unit_price < 10000;
          avg
---------------------------------------------------------------------
 4968.4946466804019323
(1 row)

-- Check unsupported subqueries in target list
SELECT (SELECT 1) FROM orders_subquery;
ERROR:  could not run distributed query with subquery outside the FROM, WHERE and HAVING clauses
SELECT sum((SELECT 1)) FROM orders_subquery;
ERROR:  could not run distributed query with subquery outside the FROM, WHERE and HAVING clauses
-- Check that if subquery is pulled, we don't error and run query properly.
SELECT count(*) FROM
(
	SELECT l_orderkey FROM (
		(SELECT l_orderkey FROM lineitem_subquery) UNION
		(SELECT l_orderkey FROM lineitem_subquery)
	) a
	WHERE l_orderkey = 1
) b;
 count
---------------------------------------------------------------------
     1
(1 row)

SELECT count(*) FROM
(
	SELECT * FROM (
		(SELECT * FROM lineitem_subquery) UNION
		(SELECT * FROM lineitem_subquery)
	) a
	WHERE l_orderkey = 1
) b;
 count
---------------------------------------------------------------------
     6
(1 row)

SELECT max(l_orderkey) FROM
(
	SELECT l_orderkey FROM (
		SELECT
			l_orderkey
		FROM
			lineitem_subquery
		WHERE
			l_orderkey < 20000
		GROUP BY
			l_orderkey
  ) z
) y;
  max
---------------------------------------------------------------------
 14947
(1 row)

-- Subqueries filter by 2 different users
SELECT *
FROM
  (SELECT *
   FROM
     (SELECT user_id,
             sum(value_2) AS counter
      FROM events_table
      WHERE user_id = 2
      GROUP BY user_id) AS foo,
     (SELECT user_id,
             sum(value_2) AS counter
      FROM events_table
      WHERE user_id = 3
      GROUP BY user_id) AS bar
   WHERE foo.user_id = bar.user_id ) AS baz;
 user_id | counter | user_id | counter
---------------------------------------------------------------------
(0 rows)

-- Subqueries filter by different users, one of which overlaps
SELECT *
FROM
  (SELECT *
   FROM
     (SELECT user_id,
             sum(value_2) AS counter
      FROM events_table
      WHERE user_id = 2
        OR user_id = 3
      GROUP BY user_id) AS foo,
     (SELECT user_id,
             sum(value_2) AS counter
      FROM events_table
      WHERE user_id = 2
      GROUP BY user_id) AS bar
   WHERE foo.user_id = bar.user_id ) AS baz
ORDER BY 1,2
LIMIT 5;
 user_id | counter | user_id | counter
---------------------------------------------------------------------
       2 |      57 |       2 |      57
(1 row)

-- Add one more shard to one relation, then test if we error out because of different
-- shard counts for joining relations.
SELECT master_create_empty_shard('orders_subquery') AS new_shard_id
\gset
UPDATE pg_dist_shard SET shardminvalue = 15000, shardmaxvalue = 20000
WHERE shardid = :new_shard_id;
SELECT
	avg(unit_price)
FROM
	(SELECT
		l_orderkey,
		avg(o_totalprice / l_quantity) AS unit_price
	FROM
		lineitem_subquery,
		orders_subquery
	WHERE
		l_orderkey = o_orderkey
	GROUP BY
		l_orderkey) AS unit_prices;
ERROR:  cannot push down this subquery
DETAIL:  Shards of relations in subquery need to have 1-to-1 shard partitioning
-- Check that we can prune shards in subqueries with VARCHAR partition columns
CREATE TABLE subquery_pruning_varchar_test_table
(
   a varchar,
   b int
);
SET citus.shard_replication_factor TO 1;
SELECT create_distributed_table('subquery_pruning_varchar_test_table', 'a', 'hash');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

-- temporarily disable router executor to test pruning behaviour of subquery pushdown
SET citus.enable_router_execution TO off;
SET client_min_messages TO DEBUG2;
SELECT * FROM
	(SELECT count(*) FROM subquery_pruning_varchar_test_table WHERE a = 'onder' GROUP BY a)
AS foo;
DEBUG:  Router planner not enabled.
 count
---------------------------------------------------------------------
(0 rows)

SELECT * FROM
	(SELECT count(*) FROM subquery_pruning_varchar_test_table WHERE 'eren' = a GROUP BY a)
AS foo;
DEBUG:  Router planner not enabled.
 count
---------------------------------------------------------------------
(0 rows)

SET client_min_messages TO NOTICE;
-- test subquery join on VARCHAR partition column
SELECT * FROM
	(SELECT
		a_inner AS a
	FROM
		(SELECT
			subquery_pruning_varchar_test_table.a AS a_inner
		FROM
		 	subquery_pruning_varchar_test_table
		GROUP BY
		  	subquery_pruning_varchar_test_table.a
		HAVING
		  	count(subquery_pruning_varchar_test_table.a) < 3)
		AS f1,
		(SELECT
		 	subquery_pruning_varchar_test_table.a
		FROM
		  	subquery_pruning_varchar_test_table
		GROUP BY
		  	subquery_pruning_varchar_test_table.a
		HAVING
		  	sum(coalesce(subquery_pruning_varchar_test_table.b,0)) > 20.0)
		AS f2
	WHERE
		f1.a_inner = f2.a
	GROUP BY
		a_inner)
AS foo;
 a
---------------------------------------------------------------------
(0 rows)

DROP TABLE subquery_pruning_varchar_test_table;
RESET citus.enable_router_execution;
-- Simple join subquery pushdown
SELECT
	avg(array_length(events, 1)) AS event_average
FROM
	(SELECT
		tenant_id,
		user_id,
		array_agg(event_type ORDER BY event_time) AS events
	FROM
		(SELECT
			(users.composite_id).tenant_id,
			(users.composite_id).user_id,
			event_type,
			events.event_time
		FROM
			users,
			events
		WHERE
			(users.composite_id) = (events.composite_id) AND
			users.composite_id >= '(1, -9223372036854775808)'::user_composite_type AND
			users.composite_id <= '(1, 9223372036854775807)'::user_composite_type AND
			event_type IN ('click', 'submit', 'pay')) AS subquery
	GROUP BY
		tenant_id,
		user_id) AS subquery;
   event_average
---------------------------------------------------------------------
 3.6666666666666667
(1 row)

-- Union and left join subquery pushdown
SELECT
	avg(array_length(events, 1)) AS event_average,
	hasdone
FROM
	(SELECT
		subquery_1.tenant_id,
		subquery_1.user_id,
		array_agg(event ORDER BY event_time) AS events,
		COALESCE(hasdone, 'Has not done paying') AS hasdone
	FROM
	(
		(SELECT
			(users.composite_id).tenant_id,
			(users.composite_id).user_id,
			(users.composite_id) as composite_id,
			'action=>1'AS event,
			events.event_time
		FROM
			users,
			events
		WHERE
			(users.composite_id) = (events.composite_id) AND
			users.composite_id >= '(1, -9223372036854775808)'::user_composite_type AND
			users.composite_id <= '(1, 9223372036854775807)'::user_composite_type AND
			event_type = 'click')
		UNION
		(SELECT
			(users.composite_id).tenant_id,
			(users.composite_id).user_id,
			(users.composite_id) as composite_id,
			'action=>2'AS event,
			events.event_time
		FROM
			users,
			events
		WHERE
			(users.composite_id) = (events.composite_id) AND
			users.composite_id >= '(1, -9223372036854775808)'::user_composite_type AND
			users.composite_id <= '(1, 9223372036854775807)'::user_composite_type AND
			event_type = 'submit')
	) AS subquery_1
	LEFT JOIN
	(SELECT
		DISTINCT ON ((composite_id).tenant_id, (composite_id).user_id) composite_id,
		(composite_id).tenant_id,
		(composite_id).user_id,
		'Has done paying'::TEXT AS hasdone
	FROM
		events
	WHERE
		events.composite_id >= '(1, -9223372036854775808)'::user_composite_type AND
		events.composite_id <= '(1, 9223372036854775807)'::user_composite_type AND
		event_type = 'pay') AS subquery_2
	ON
		subquery_1.composite_id = subquery_2.composite_id
	GROUP BY
		subquery_1.tenant_id,
		subquery_1.user_id,
		hasdone) AS subquery_top
GROUP BY
	hasdone
ORDER BY
    event_average DESC;
   event_average    |       hasdone
---------------------------------------------------------------------
 4.0000000000000000 | Has not done paying
 2.5000000000000000 | Has done paying
(2 rows)

-- Union, left join and having subquery pushdown
SELECT
	avg(array_length(events, 1)) AS event_average,
	count_pay
	FROM (
  SELECT
	subquery_1.tenant_id,
	subquery_1.user_id,
	array_agg(event ORDER BY event_time) AS events,
	COALESCE(count_pay, 0) AS count_pay
  FROM
	(
		(SELECT
			(users.composite_id).tenant_id,
			(users.composite_id).user_id,
			(users.composite_id),
			'action=>1'AS event,
			events.event_time
		FROM
			users,
			events
		WHERE
			(users.composite_id) = (events.composite_id) AND
			users.composite_id >= '(1, -9223372036854775808)'::user_composite_type AND
			users.composite_id <= '(1, 9223372036854775807)'::user_composite_type AND
			event_type = 'click')
		UNION
		(SELECT
			(users.composite_id).tenant_id,
			(users.composite_id).user_id,
			(users.composite_id),
			'action=>2'AS event,
			events.event_time
		FROM
			users,
			events
		WHERE
			(users.composite_id) = (events.composite_id) AND
			users.composite_id >= '(1, -9223372036854775808)'::user_composite_type AND
			users.composite_id <= '(1, 9223372036854775807)'::user_composite_type AND
			event_type = 'submit')
	) AS subquery_1
	LEFT JOIN
		(SELECT
			(composite_id).tenant_id,
			(composite_id).user_id,
			composite_id,
			COUNT(*) AS count_pay
		FROM
			events
		WHERE
			events.composite_id >= '(1, -9223372036854775808)'::user_composite_type AND
			events.composite_id <= '(1, 9223372036854775807)'::user_composite_type AND
			event_type = 'pay'
		GROUP BY
			composite_id
		HAVING
			COUNT(*) > 2) AS subquery_2
	ON
		subquery_1.composite_id = subquery_2.composite_id
	GROUP BY
		subquery_1.tenant_id,
		subquery_1.user_id,
		count_pay) AS subquery_top
WHERE
	array_ndims(events) > 0
GROUP BY
	count_pay
ORDER BY
	count_pay;
   event_average    | count_pay
---------------------------------------------------------------------
 3.0000000000000000 |         0
(1 row)

-- Lateral join subquery pushdown
-- set subquery_pushdown since there is limit in the query
SET citus.subquery_pushdown to ON;
SELECT
	tenant_id,
	user_id,
	user_lastseen,
	event_array
FROM
	(SELECT
		tenant_id,
		user_id,
		max(lastseen) as user_lastseen,
		array_agg(event_type ORDER BY event_time) AS event_array
	FROM
		(SELECT
			(composite_id).tenant_id,
			(composite_id).user_id,
			composite_id,
			lastseen
		FROM
			users
		WHERE
			composite_id >= '(1, -9223372036854775808)'::user_composite_type AND
			composite_id <= '(1, 9223372036854775807)'::user_composite_type
		ORDER BY
			lastseen DESC
		LIMIT
			10
		) AS subquery_top
		LEFT JOIN LATERAL
			(SELECT
				event_type,
				event_time
			FROM
				events
			WHERE
				(composite_id) = subquery_top.composite_id
			ORDER BY
				event_time DESC
			LIMIT
				99) AS subquery_lateral
		ON
			true
		GROUP BY
			tenant_id,
			user_id
	) AS shard_union
ORDER BY
	user_lastseen DESC
LIMIT
	10;
 tenant_id | user_id | user_lastseen |        event_array
---------------------------------------------------------------------
         1 |    1003 |    1472807315 | {click,click,click,submit}
         1 |    1002 |    1472807215 | {click,click,submit,pay}
         1 |    1001 |    1472807115 | {click,submit,pay}
(3 rows)

-- cleanup the tables and the type & functions
-- also set the min messages to WARNING to skip
-- CASCADE NOTICE messagez
SET client_min_messages TO WARNING;
DROP TABLE users, events;
DROP TYPE user_composite_type CASCADE;
SET client_min_messages TO DEFAULT;
SET citus.subquery_pushdown to OFF;
