mirror of https://github.com/citusdata/citus.git
Add regression tests for recursive subquery planning
parent
0d5a4b9c72
commit
e2a5124830
|
@ -346,15 +346,28 @@ SELECT count(*) FROM lineitem, orders WHERE l_orderkey + 1 = o_orderkey;
|
||||||
ERROR: cannot perform local joins that involve expressions
|
ERROR: cannot perform local joins that involve expressions
|
||||||
DETAIL: local joins can be performed between columns only
|
DETAIL: local joins can be performed between columns only
|
||||||
-- Check that we can issue limit/offset queries
|
-- Check that we can issue limit/offset queries
|
||||||
-- OFFSET in subqueries are not supported
|
-- the subquery is recursively planned since it contains OFFSET, which is not pushdownable
|
||||||
-- Error in the planner when single repartition subquery
|
SELECT * FROM (SELECT o_custkey FROM orders GROUP BY o_custkey ORDER BY o_custkey OFFSET 20) sq ORDER BY 1 LIMIT 5;
|
||||||
SELECT * FROM (SELECT o_custkey FROM orders GROUP BY o_custkey ORDER BY o_custkey OFFSET 20) sq;
|
o_custkey
|
||||||
ERROR: cannot perform distributed planning on this query
|
-----------
|
||||||
DETAIL: Subqueries with offset are not supported yet
|
35
|
||||||
-- Error in the optimizer when subquery pushdown is on
|
37
|
||||||
SELECT * FROM (SELECT o_orderkey FROM orders ORDER BY o_orderkey OFFSET 20) sq;
|
38
|
||||||
ERROR: cannot perform distributed planning on this query
|
40
|
||||||
DETAIL: Subqueries with offset are not supported yet
|
41
|
||||||
|
(5 rows)
|
||||||
|
|
||||||
|
-- the subquery is recursively planned since it contains OFFSET, which is not pushdownable
|
||||||
|
SELECT * FROM (SELECT o_orderkey FROM orders ORDER BY o_orderkey OFFSET 20) sq ORDER BY 1 LIMIT 5;
|
||||||
|
o_orderkey
|
||||||
|
------------
|
||||||
|
69
|
||||||
|
70
|
||||||
|
71
|
||||||
|
96
|
||||||
|
97
|
||||||
|
(5 rows)
|
||||||
|
|
||||||
-- Simple LIMIT/OFFSET with ORDER BY
|
-- Simple LIMIT/OFFSET with ORDER BY
|
||||||
SELECT o_orderkey FROM orders ORDER BY o_orderkey LIMIT 10 OFFSET 20;
|
SELECT o_orderkey FROM orders ORDER BY o_orderkey LIMIT 10 OFFSET 20;
|
||||||
o_orderkey
|
o_orderkey
|
||||||
|
|
|
@ -0,0 +1,507 @@
|
||||||
|
--
|
||||||
|
-- MULTI_COMPLEX_EXPRESSIONS
|
||||||
|
--
|
||||||
|
-- Check that we can correctly handle complex expressions and aggregates.
|
||||||
|
SELECT sum(l_quantity) / avg(l_quantity) FROM lineitem;
|
||||||
|
?column?
|
||||||
|
------------------------
|
||||||
|
12000.0000000000000000
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT sum(l_quantity) / (10 * avg(l_quantity)) FROM lineitem;
|
||||||
|
?column?
|
||||||
|
-----------------------
|
||||||
|
1200.0000000000000000
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT (sum(l_quantity) / (10 * avg(l_quantity))) + 11 FROM lineitem;
|
||||||
|
?column?
|
||||||
|
-----------------------
|
||||||
|
1211.0000000000000000
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT avg(l_quantity) as average FROM lineitem;
|
||||||
|
average
|
||||||
|
---------------------
|
||||||
|
25.4462500000000000
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT 100 * avg(l_quantity) as average_times_hundred FROM lineitem;
|
||||||
|
average_times_hundred
|
||||||
|
-----------------------
|
||||||
|
2544.6250000000000000
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT 100 * avg(l_quantity) / 10 as average_times_ten FROM lineitem;
|
||||||
|
average_times_ten
|
||||||
|
----------------------
|
||||||
|
254.4625000000000000
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT l_quantity, 10 * count(*) count_quantity FROM lineitem
|
||||||
|
GROUP BY l_quantity ORDER BY count_quantity, l_quantity;
|
||||||
|
l_quantity | count_quantity
|
||||||
|
------------+----------------
|
||||||
|
44.00 | 2150
|
||||||
|
38.00 | 2160
|
||||||
|
45.00 | 2180
|
||||||
|
13.00 | 2190
|
||||||
|
47.00 | 2200
|
||||||
|
29.00 | 2220
|
||||||
|
36.00 | 2230
|
||||||
|
49.00 | 2230
|
||||||
|
3.00 | 2270
|
||||||
|
35.00 | 2280
|
||||||
|
18.00 | 2290
|
||||||
|
31.00 | 2290
|
||||||
|
43.00 | 2290
|
||||||
|
14.00 | 2300
|
||||||
|
16.00 | 2300
|
||||||
|
17.00 | 2300
|
||||||
|
26.00 | 2300
|
||||||
|
7.00 | 2320
|
||||||
|
10.00 | 2340
|
||||||
|
34.00 | 2340
|
||||||
|
15.00 | 2350
|
||||||
|
25.00 | 2360
|
||||||
|
33.00 | 2360
|
||||||
|
42.00 | 2360
|
||||||
|
2.00 | 2370
|
||||||
|
12.00 | 2410
|
||||||
|
37.00 | 2410
|
||||||
|
6.00 | 2420
|
||||||
|
22.00 | 2420
|
||||||
|
1.00 | 2430
|
||||||
|
19.00 | 2430
|
||||||
|
4.00 | 2440
|
||||||
|
20.00 | 2460
|
||||||
|
48.00 | 2460
|
||||||
|
41.00 | 2470
|
||||||
|
24.00 | 2490
|
||||||
|
27.00 | 2490
|
||||||
|
8.00 | 2500
|
||||||
|
11.00 | 2500
|
||||||
|
5.00 | 2540
|
||||||
|
21.00 | 2550
|
||||||
|
32.00 | 2550
|
||||||
|
9.00 | 2580
|
||||||
|
39.00 | 2600
|
||||||
|
46.00 | 2600
|
||||||
|
50.00 | 2600
|
||||||
|
23.00 | 2610
|
||||||
|
30.00 | 2640
|
||||||
|
40.00 | 2690
|
||||||
|
28.00 | 2730
|
||||||
|
(50 rows)
|
||||||
|
|
||||||
|
-- Check that we can handle complex select clause expressions.
|
||||||
|
SELECT count(*) FROM lineitem
|
||||||
|
WHERE octet_length(l_comment || l_comment) > 40;
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
8148
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT count(*) FROM lineitem
|
||||||
|
WHERE octet_length(concat(l_comment, l_comment)) > 40;
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
8148
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT count(*) FROM lineitem
|
||||||
|
WHERE octet_length(l_comment) + octet_length('randomtext'::text) > 40;
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
4611
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT count(*) FROM lineitem
|
||||||
|
WHERE octet_length(l_comment) + 10 > 40;
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
4611
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT count(*) FROM lineitem
|
||||||
|
WHERE (l_receiptdate::timestamp - l_shipdate::timestamp) > interval '5 days';
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
10008
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- can push down queries where no columns present on the WHERE clause
|
||||||
|
SELECT count(*) FROM lineitem WHERE random() = -0.1;
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
0
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- boolean tests can be pushed down
|
||||||
|
SELECT count(*) FROM lineitem
|
||||||
|
WHERE (l_partkey > 10000) is true;
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
11423
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- scalar array operator expressions can be pushed down
|
||||||
|
SELECT count(*) FROM lineitem
|
||||||
|
WHERE l_partkey = ANY(ARRAY[19353, 19354, 19355]);
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
1
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- some more scalar array operator expressions
|
||||||
|
SELECT count(*) FROM lineitem
|
||||||
|
WHERE l_partkey = ALL(ARRAY[19353]);
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
1
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- operator expressions involving arrays
|
||||||
|
SELECT count(*) FROM lineitem
|
||||||
|
WHERE ARRAY[19353, 19354, 19355] @> ARRAY[l_partkey];
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
1
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- coerced via io expressions can be pushed down
|
||||||
|
SELECT count(*) FROM lineitem
|
||||||
|
WHERE (l_quantity/100)::int::bool::text::bool;
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
260
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- case expressions can be pushed down
|
||||||
|
SELECT count(*) FROM lineitem
|
||||||
|
WHERE (CASE WHEN l_orderkey > 4000 THEN l_partkey / 100 > 1 ELSE false END);
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
7948
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- coalesce expressions can be pushed down
|
||||||
|
SELECT count(*) FROM lineitem
|
||||||
|
WHERE COALESCE((l_partkey/50000)::bool, false);
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
9122
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- nullif expressions can be pushed down
|
||||||
|
SELECT count(*) FROM lineitem
|
||||||
|
WHERE NULLIF((l_partkey/50000)::bool, false);
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
9122
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- null test expressions can be pushed down
|
||||||
|
SELECT count(*) FROM orders
|
||||||
|
WHERE o_comment IS NOT null;
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
2984
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- functions can be pushed down
|
||||||
|
SELECT count(*) FROM lineitem
|
||||||
|
WHERE isfinite(l_shipdate);
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
12000
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- constant expressions can be pushed down
|
||||||
|
SELECT count(*) FROM lineitem
|
||||||
|
WHERE 0 != 0;
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
0
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- distinct expressions can be pushed down
|
||||||
|
SELECT count(*) FROM lineitem
|
||||||
|
WHERE l_partkey IS DISTINCT FROM 50040;
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
11999
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- row compare expression can be pushed down
|
||||||
|
SELECT count(*) FROM lineitem
|
||||||
|
WHERE row(l_partkey, 2, 3) > row(2000, 2, 3);
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
11882
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- combination of different expressions can be pushed down
|
||||||
|
SELECT count(*) FROM lineitem
|
||||||
|
WHERE
|
||||||
|
(l_quantity/100)::int::bool::text::bool AND
|
||||||
|
CASE WHEN l_orderkey > 4000 THEN l_partkey / 100 > 1 ELSE false END AND
|
||||||
|
COALESCE((l_partkey/50000)::bool, false) AND
|
||||||
|
NULLIF((l_partkey/50000)::bool, false) AND
|
||||||
|
isfinite(l_shipdate) AND
|
||||||
|
l_partkey IS DISTINCT FROM 50040 AND
|
||||||
|
row(l_partkey, 2, 3) > row(2000, 2, 3);
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
137
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- constant expression in the WHERE clause with a column in the target list
|
||||||
|
SELECT l_linenumber FROM lineitem
|
||||||
|
WHERE
|
||||||
|
1!=0
|
||||||
|
ORDER BY
|
||||||
|
l_linenumber
|
||||||
|
LIMIT 1;
|
||||||
|
l_linenumber
|
||||||
|
--------------
|
||||||
|
1
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- constant expression in the WHERE clause with expressions and a column the target list
|
||||||
|
SELECT count(*) * l_discount as total_discount, count(*), sum(l_tax), l_discount FROM lineitem
|
||||||
|
WHERE
|
||||||
|
1!=0
|
||||||
|
GROUP BY
|
||||||
|
l_discount
|
||||||
|
ORDER BY
|
||||||
|
total_discount DESC, sum(l_tax) DESC;
|
||||||
|
total_discount | count | sum | l_discount
|
||||||
|
----------------+-------+-------+------------
|
||||||
|
104.80 | 1048 | 41.08 | 0.10
|
||||||
|
98.55 | 1095 | 44.15 | 0.09
|
||||||
|
90.64 | 1133 | 45.94 | 0.08
|
||||||
|
71.05 | 1015 | 41.19 | 0.07
|
||||||
|
69.42 | 1157 | 45.75 | 0.06
|
||||||
|
53.60 | 1072 | 42.82 | 0.05
|
||||||
|
43.64 | 1091 | 44.40 | 0.04
|
||||||
|
32.55 | 1085 | 43.30 | 0.03
|
||||||
|
22.22 | 1111 | 45.07 | 0.02
|
||||||
|
11.22 | 1122 | 44.54 | 0.01
|
||||||
|
0.00 | 1071 | 44.00 | 0.00
|
||||||
|
(11 rows)
|
||||||
|
|
||||||
|
-- distinct expressions in the WHERE clause with a column in the target list
|
||||||
|
SELECT l_linenumber FROM lineitem
|
||||||
|
WHERE
|
||||||
|
l_linenumber IS DISTINCT FROM 1 AND
|
||||||
|
l_orderkey IS DISTINCT FROM 8997
|
||||||
|
ORDER BY
|
||||||
|
l_linenumber
|
||||||
|
LIMIT 1;
|
||||||
|
l_linenumber
|
||||||
|
--------------
|
||||||
|
2
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- distinct expressions in the WHERE clause with expressions and a column the target list
|
||||||
|
SELECT max(l_linenumber), min(l_discount), l_receiptdate FROM lineitem
|
||||||
|
WHERE
|
||||||
|
l_linenumber IS DISTINCT FROM 1 AND
|
||||||
|
l_orderkey IS DISTINCT FROM 8997
|
||||||
|
GROUP BY
|
||||||
|
l_receiptdate
|
||||||
|
ORDER BY
|
||||||
|
l_receiptdate
|
||||||
|
LIMIT 1;
|
||||||
|
max | min | l_receiptdate
|
||||||
|
-----+------+---------------
|
||||||
|
3 | 0.07 | 01-09-1992
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- Check that we can handle implicit and explicit join clause definitions.
|
||||||
|
SELECT count(*) FROM lineitem, orders
|
||||||
|
WHERE l_orderkey = o_orderkey AND l_quantity < 5;
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
951
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT count(*) FROM lineitem
|
||||||
|
JOIN orders ON l_orderkey = o_orderkey AND l_quantity < 5;
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
951
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT count(*) FROM lineitem JOIN orders ON l_orderkey = o_orderkey
|
||||||
|
WHERE l_quantity < 5;
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
951
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- Check that we make sure local joins are between columns only.
|
||||||
|
SELECT count(*) FROM lineitem, orders WHERE l_orderkey + 1 = o_orderkey;
|
||||||
|
ERROR: cannot perform local joins that involve expressions
|
||||||
|
DETAIL: local joins can be performed between columns only
|
||||||
|
-- Check that we can issue limit/offset queries
|
||||||
|
-- the subquery is recursively planned since it contains OFFSET, which is not pushdownable
|
||||||
|
SELECT * FROM (SELECT o_custkey FROM orders GROUP BY o_custkey ORDER BY o_custkey OFFSET 20) sq ORDER BY 1 LIMIT 5;
|
||||||
|
ERROR: cannot perform distributed planning on this query
|
||||||
|
DETAIL: Subqueries with offset are not supported yet
|
||||||
|
-- the subquery is recursively planned since it contains OFFSET, which is not pushdownable
|
||||||
|
SELECT * FROM (SELECT o_orderkey FROM orders ORDER BY o_orderkey OFFSET 20) sq ORDER BY 1 LIMIT 5;
|
||||||
|
ERROR: cannot perform distributed planning on this query
|
||||||
|
DETAIL: Subqueries with offset are not supported yet
|
||||||
|
-- Simple LIMIT/OFFSET with ORDER BY
|
||||||
|
SELECT o_orderkey FROM orders ORDER BY o_orderkey LIMIT 10 OFFSET 20;
|
||||||
|
o_orderkey
|
||||||
|
------------
|
||||||
|
69
|
||||||
|
70
|
||||||
|
71
|
||||||
|
96
|
||||||
|
97
|
||||||
|
98
|
||||||
|
99
|
||||||
|
100
|
||||||
|
101
|
||||||
|
102
|
||||||
|
(10 rows)
|
||||||
|
|
||||||
|
-- LIMIT/OFFSET with a subquery
|
||||||
|
SET citus.task_executor_type TO 'task-tracker';
|
||||||
|
SELECT
|
||||||
|
customer_keys.o_custkey,
|
||||||
|
SUM(order_count) AS total_order_count
|
||||||
|
FROM
|
||||||
|
(SELECT o_custkey, o_orderstatus, COUNT(*) AS order_count
|
||||||
|
FROM orders GROUP BY o_custkey, o_orderstatus ) customer_keys
|
||||||
|
GROUP BY
|
||||||
|
customer_keys.o_custkey
|
||||||
|
ORDER BY
|
||||||
|
customer_keys.o_custkey DESC
|
||||||
|
LIMIT 10 OFFSET 20;
|
||||||
|
o_custkey | total_order_count
|
||||||
|
-----------+-------------------
|
||||||
|
1466 | 1
|
||||||
|
1465 | 2
|
||||||
|
1463 | 4
|
||||||
|
1462 | 10
|
||||||
|
1460 | 1
|
||||||
|
1459 | 6
|
||||||
|
1457 | 1
|
||||||
|
1456 | 3
|
||||||
|
1454 | 2
|
||||||
|
1453 | 5
|
||||||
|
(10 rows)
|
||||||
|
|
||||||
|
SET citus.task_executor_type TO 'real-time';
|
||||||
|
SET client_min_messages TO DEBUG1;
|
||||||
|
-- Ensure that we push down LIMIT and OFFSET properly
|
||||||
|
-- No Group-By -> Push Down
|
||||||
|
CREATE TEMP TABLE temp_limit_test_1 AS
|
||||||
|
SELECT o_custkey FROM orders LIMIT 10 OFFSET 15;
|
||||||
|
DEBUG: push down of limit count: 25
|
||||||
|
-- GROUP BY without ORDER BY -> No push-down
|
||||||
|
CREATE TEMP TABLE temp_limit_test_2 AS
|
||||||
|
SELECT o_custkey FROM orders GROUP BY o_custkey LIMIT 10 OFFSET 15;
|
||||||
|
-- GROUP BY and ORDER BY non-aggregate -> push-down
|
||||||
|
CREATE TEMP TABLE temp_limit_test_3 AS
|
||||||
|
SELECT o_custkey FROM orders GROUP BY o_custkey ORDER BY o_custkey LIMIT 10 OFFSET 15;
|
||||||
|
DEBUG: push down of limit count: 25
|
||||||
|
-- GROUP BY and ORDER BY aggregate -> No push-down
|
||||||
|
CREATE TEMP TABLE temp_limit_test_4 AS
|
||||||
|
SELECT o_custkey, COUNT(*) AS ccnt FROM orders GROUP BY o_custkey ORDER BY ccnt DESC LIMIT 10 OFFSET 15;
|
||||||
|
-- OFFSET without LIMIT
|
||||||
|
SELECT o_custkey FROM orders ORDER BY o_custkey OFFSET 2980;
|
||||||
|
o_custkey
|
||||||
|
-----------
|
||||||
|
1498
|
||||||
|
1499
|
||||||
|
1499
|
||||||
|
1499
|
||||||
|
(4 rows)
|
||||||
|
|
||||||
|
-- LIMIT/OFFSET with Joins
|
||||||
|
SELECT
|
||||||
|
li.l_partkey,
|
||||||
|
o.o_custkey,
|
||||||
|
li.l_quantity
|
||||||
|
FROM
|
||||||
|
lineitem li JOIN orders o ON li.l_orderkey = o.o_orderkey
|
||||||
|
WHERE
|
||||||
|
li.l_quantity > 25
|
||||||
|
ORDER BY 1, 2, 3
|
||||||
|
LIMIT 10 OFFSET 20;
|
||||||
|
DEBUG: push down of limit count: 30
|
||||||
|
l_partkey | o_custkey | l_quantity
|
||||||
|
-----------+-----------+------------
|
||||||
|
655 | 58 | 50.00
|
||||||
|
669 | 319 | 34.00
|
||||||
|
699 | 1255 | 50.00
|
||||||
|
716 | 61 | 45.00
|
||||||
|
723 | 14 | 36.00
|
||||||
|
802 | 754 | 50.00
|
||||||
|
831 | 589 | 32.00
|
||||||
|
835 | 67 | 33.00
|
||||||
|
864 | 439 | 32.00
|
||||||
|
875 | 13 | 43.00
|
||||||
|
(10 rows)
|
||||||
|
|
||||||
|
RESET client_min_messages;
|
||||||
|
-- FILTERs
|
||||||
|
SELECT
|
||||||
|
l_orderkey,
|
||||||
|
sum(l_extendedprice),
|
||||||
|
sum(l_extendedprice) FILTER (WHERE l_shipmode = 'AIR'),
|
||||||
|
count(*),
|
||||||
|
count(*) FILTER (WHERE l_shipmode = 'AIR'),
|
||||||
|
max(l_extendedprice),
|
||||||
|
max(l_extendedprice) FILTER (WHERE l_quantity < 30)
|
||||||
|
FROM lineitem
|
||||||
|
GROUP BY l_orderkey
|
||||||
|
ORDER BY 2 DESC, 1 DESC
|
||||||
|
LIMIT 10;
|
||||||
|
l_orderkey | sum | sum | count | count | max | max
|
||||||
|
------------+-----------+-----------+-------+-------+-----------+----------
|
||||||
|
12804 | 440012.71 | 45788.16 | 7 | 1 | 94398.00 | 45788.16
|
||||||
|
9863 | 412560.63 | 175647.63 | 7 | 3 | 85723.77 | 50769.14
|
||||||
|
2567 | 412076.77 | 59722.26 | 7 | 1 | 94894.00 | 9784.02
|
||||||
|
11142 | 410502.38 | 44965.95 | 7 | 1 | 83989.44 | 44965.95
|
||||||
|
12039 | 407048.94 | 76406.30 | 7 | 2 | 94471.02 | 19679.30
|
||||||
|
2306 | 405629.96 | 28032.60 | 7 | 1 | 92838.00 | 44384.50
|
||||||
|
5606 | 403595.91 | 36531.51 | 7 | 2 | 94890.18 | 30582.75
|
||||||
|
11296 | 399079.89 | | 6 | 0 | 102449.00 | 33122.93
|
||||||
|
11046 | 391163.26 | 31436.34 | 7 | 2 | 94506.24 | 47519.76
|
||||||
|
4421 | 387313.12 | | 7 | 0 | 67301.52 | 23783.40
|
||||||
|
(10 rows)
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
l_orderkey,
|
||||||
|
sum(l_extendedprice),
|
||||||
|
sum(l_extendedprice) FILTER (WHERE l_shipmode = 'AIR'),
|
||||||
|
count(*),
|
||||||
|
count(*) FILTER (WHERE l_shipmode = 'AIR'),
|
||||||
|
max(l_extendedprice),
|
||||||
|
max(l_extendedprice) FILTER (WHERE l_quantity < 30)
|
||||||
|
FROM lineitem
|
||||||
|
GROUP BY l_orderkey
|
||||||
|
HAVING count(*) FILTER (WHERE l_shipmode = 'AIR') > 1
|
||||||
|
ORDER BY 2 DESC, 1 DESC
|
||||||
|
LIMIT 10;
|
||||||
|
l_orderkey | sum | sum | count | count | max | max
|
||||||
|
------------+-----------+-----------+-------+-------+----------+----------
|
||||||
|
9863 | 412560.63 | 175647.63 | 7 | 3 | 85723.77 | 50769.14
|
||||||
|
12039 | 407048.94 | 76406.30 | 7 | 2 | 94471.02 | 19679.30
|
||||||
|
5606 | 403595.91 | 36531.51 | 7 | 2 | 94890.18 | 30582.75
|
||||||
|
11046 | 391163.26 | 31436.34 | 7 | 2 | 94506.24 | 47519.76
|
||||||
|
14499 | 384140.30 | 67867.08 | 7 | 2 | 84335.36 | 46169.75
|
||||||
|
11623 | 380598.48 | 133709.82 | 7 | 2 | 93701.54 | 21487.65
|
||||||
|
10787 | 375688.09 | 99424.78 | 7 | 2 | 76732.67 | 50946.91
|
||||||
|
12902 | 358191.24 | 76891.00 | 7 | 2 | 82008.08 | 35602.08
|
||||||
|
3747 | 353701.23 | 68592.23 | 7 | 2 | 67181.10 | 46252.77
|
||||||
|
5158 | 349889.05 | 159753.19 | 7 | 3 | 78714.67 | 29729.20
|
||||||
|
(10 rows)
|
||||||
|
|
|
@ -1047,7 +1047,7 @@ FROM (SELECT SUM(raw_events_second.value_4) AS v4,
|
||||||
GROUP BY raw_events_second.user_id) AS foo;
|
GROUP BY raw_events_second.user_id) AS foo;
|
||||||
ERROR: cannot perform distributed planning for the given modification
|
ERROR: cannot perform distributed planning for the given modification
|
||||||
DETAIL: Select query cannot be pushed down to the worker.
|
DETAIL: Select query cannot be pushed down to the worker.
|
||||||
-- INSERT partition column does not match with SELECT partition column
|
-- INSERT returns NULL partition key value via coordinator
|
||||||
INSERT INTO agg_events
|
INSERT INTO agg_events
|
||||||
(value_4_agg,
|
(value_4_agg,
|
||||||
value_1_agg,
|
value_1_agg,
|
||||||
|
@ -1064,9 +1064,22 @@ FROM (SELECT SUM(raw_events_second.value_4) AS v4,
|
||||||
GROUP BY raw_events_second.value_3) AS foo;
|
GROUP BY raw_events_second.value_3) AS foo;
|
||||||
DEBUG: Group by list without distribution column is not allowed in distributed INSERT ... SELECT queries
|
DEBUG: Group by list without distribution column is not allowed in distributed INSERT ... SELECT queries
|
||||||
DEBUG: Collecting INSERT ... SELECT results on coordinator
|
DEBUG: Collecting INSERT ... SELECT results on coordinator
|
||||||
ERROR: cannot push down this subquery
|
DEBUG: join prunable for intervals [-2147483648,-1073741825] and [-1073741824,-1]
|
||||||
DETAIL: Group by list without partition column is currently unsupported
|
DEBUG: join prunable for intervals [-2147483648,-1073741825] and [0,1073741823]
|
||||||
|
DEBUG: join prunable for intervals [-2147483648,-1073741825] and [1073741824,2147483647]
|
||||||
|
DEBUG: join prunable for intervals [-1073741824,-1] and [-2147483648,-1073741825]
|
||||||
|
DEBUG: join prunable for intervals [-1073741824,-1] and [0,1073741823]
|
||||||
|
DEBUG: join prunable for intervals [-1073741824,-1] and [1073741824,2147483647]
|
||||||
|
DEBUG: join prunable for intervals [0,1073741823] and [-2147483648,-1073741825]
|
||||||
|
DEBUG: join prunable for intervals [0,1073741823] and [-1073741824,-1]
|
||||||
|
DEBUG: join prunable for intervals [0,1073741823] and [1073741824,2147483647]
|
||||||
|
DEBUG: join prunable for intervals [1073741824,2147483647] and [-2147483648,-1073741825]
|
||||||
|
DEBUG: join prunable for intervals [1073741824,2147483647] and [-1073741824,-1]
|
||||||
|
DEBUG: join prunable for intervals [1073741824,2147483647] and [0,1073741823]
|
||||||
DEBUG: generating subplan 86_1 for subquery SELECT sum(raw_events_second.value_4) AS v4, sum(raw_events_first.value_1) AS v1, raw_events_second.value_3 AS id FROM public.raw_events_first, public.raw_events_second WHERE (raw_events_first.user_id = raw_events_second.user_id) GROUP BY raw_events_second.value_3
|
DEBUG: generating subplan 86_1 for subquery SELECT sum(raw_events_second.value_4) AS v4, sum(raw_events_first.value_1) AS v1, raw_events_second.value_3 AS id FROM public.raw_events_first, public.raw_events_second WHERE (raw_events_first.user_id = raw_events_second.user_id) GROUP BY raw_events_second.value_3
|
||||||
|
DEBUG: Creating router plan
|
||||||
|
DEBUG: Plan is router executable
|
||||||
|
ERROR: the partition column of table public.agg_events cannot be NULL
|
||||||
-- error cases
|
-- error cases
|
||||||
-- no part column at all
|
-- no part column at all
|
||||||
INSERT INTO raw_events_second
|
INSERT INTO raw_events_second
|
||||||
|
@ -1156,8 +1169,7 @@ DETAIL: The target table's partition column should correspond to a partition co
|
||||||
DEBUG: Collecting INSERT ... SELECT results on coordinator
|
DEBUG: Collecting INSERT ... SELECT results on coordinator
|
||||||
DEBUG: Creating router plan
|
DEBUG: Creating router plan
|
||||||
DEBUG: Plan is router executable
|
DEBUG: Plan is router executable
|
||||||
-- unsupported joins between subqueries
|
-- foo2 is recursively planned and INSERT...SELECT is done via coordinator
|
||||||
-- we do not return bare partition column on the inner query
|
|
||||||
INSERT INTO agg_events
|
INSERT INTO agg_events
|
||||||
(user_id)
|
(user_id)
|
||||||
SELECT f2.id FROM
|
SELECT f2.id FROM
|
||||||
|
@ -1182,12 +1194,23 @@ FROM (SELECT SUM(raw_events_second.value_4) AS v4,
|
||||||
ON (f.id = f2.id);
|
ON (f.id = f2.id);
|
||||||
DEBUG: Group by list without distribution column is not allowed in distributed INSERT ... SELECT queries
|
DEBUG: Group by list without distribution column is not allowed in distributed INSERT ... SELECT queries
|
||||||
DEBUG: Collecting INSERT ... SELECT results on coordinator
|
DEBUG: Collecting INSERT ... SELECT results on coordinator
|
||||||
ERROR: cannot pushdown the subquery since all relations are not joined using distribution keys
|
DEBUG: join prunable for intervals [-2147483648,-1073741825] and [-1073741824,-1]
|
||||||
DETAIL: Each relation should be joined with at least one another relation using distribution keys and equality operator.
|
DEBUG: join prunable for intervals [-2147483648,-1073741825] and [0,1073741823]
|
||||||
|
DEBUG: join prunable for intervals [-2147483648,-1073741825] and [1073741824,2147483647]
|
||||||
|
DEBUG: join prunable for intervals [-1073741824,-1] and [-2147483648,-1073741825]
|
||||||
|
DEBUG: join prunable for intervals [-1073741824,-1] and [0,1073741823]
|
||||||
|
DEBUG: join prunable for intervals [-1073741824,-1] and [1073741824,2147483647]
|
||||||
|
DEBUG: join prunable for intervals [0,1073741823] and [-2147483648,-1073741825]
|
||||||
|
DEBUG: join prunable for intervals [0,1073741823] and [-1073741824,-1]
|
||||||
|
DEBUG: join prunable for intervals [0,1073741823] and [1073741824,2147483647]
|
||||||
|
DEBUG: join prunable for intervals [1073741824,2147483647] and [-2147483648,-1073741825]
|
||||||
|
DEBUG: join prunable for intervals [1073741824,2147483647] and [-1073741824,-1]
|
||||||
|
DEBUG: join prunable for intervals [1073741824,2147483647] and [0,1073741823]
|
||||||
DEBUG: generating subplan 105_1 for subquery SELECT sum(raw_events_second.value_4) AS v4, raw_events_second.value_1 AS v1, sum(raw_events_second.user_id) AS id FROM public.raw_events_first, public.raw_events_second WHERE (raw_events_first.user_id = raw_events_second.user_id) GROUP BY raw_events_second.value_1 HAVING (sum(raw_events_second.value_4) > (10)::numeric)
|
DEBUG: generating subplan 105_1 for subquery SELECT sum(raw_events_second.value_4) AS v4, raw_events_second.value_1 AS v1, sum(raw_events_second.user_id) AS id FROM public.raw_events_first, public.raw_events_second WHERE (raw_events_first.user_id = raw_events_second.user_id) GROUP BY raw_events_second.value_1 HAVING (sum(raw_events_second.value_4) > (10)::numeric)
|
||||||
-- the second part of the query is not routable since
|
-- the second part of the query is not routable since
|
||||||
-- GROUP BY not on the partition column (i.e., value_1) and thus join
|
-- GROUP BY not on the partition column (i.e., value_1) and thus join
|
||||||
-- on f.id = f2.id is not on the partition key (instead on the sum of partition key)
|
-- on f.id = f2.id is not on the partition key (instead on the sum of partition key)
|
||||||
|
-- but we still recursively plan foo2 and run the query
|
||||||
INSERT INTO agg_events
|
INSERT INTO agg_events
|
||||||
(user_id)
|
(user_id)
|
||||||
SELECT f.id FROM
|
SELECT f.id FROM
|
||||||
|
@ -1212,8 +1235,18 @@ FROM (SELECT SUM(raw_events_second.value_4) AS v4,
|
||||||
ON (f.id = f2.id);
|
ON (f.id = f2.id);
|
||||||
DEBUG: Group by list without distribution column is not allowed in distributed INSERT ... SELECT queries
|
DEBUG: Group by list without distribution column is not allowed in distributed INSERT ... SELECT queries
|
||||||
DEBUG: Collecting INSERT ... SELECT results on coordinator
|
DEBUG: Collecting INSERT ... SELECT results on coordinator
|
||||||
ERROR: cannot pushdown the subquery since all relations are not joined using distribution keys
|
DEBUG: join prunable for intervals [-2147483648,-1073741825] and [-1073741824,-1]
|
||||||
DETAIL: Each relation should be joined with at least one another relation using distribution keys and equality operator.
|
DEBUG: join prunable for intervals [-2147483648,-1073741825] and [0,1073741823]
|
||||||
|
DEBUG: join prunable for intervals [-2147483648,-1073741825] and [1073741824,2147483647]
|
||||||
|
DEBUG: join prunable for intervals [-1073741824,-1] and [-2147483648,-1073741825]
|
||||||
|
DEBUG: join prunable for intervals [-1073741824,-1] and [0,1073741823]
|
||||||
|
DEBUG: join prunable for intervals [-1073741824,-1] and [1073741824,2147483647]
|
||||||
|
DEBUG: join prunable for intervals [0,1073741823] and [-2147483648,-1073741825]
|
||||||
|
DEBUG: join prunable for intervals [0,1073741823] and [-1073741824,-1]
|
||||||
|
DEBUG: join prunable for intervals [0,1073741823] and [1073741824,2147483647]
|
||||||
|
DEBUG: join prunable for intervals [1073741824,2147483647] and [-2147483648,-1073741825]
|
||||||
|
DEBUG: join prunable for intervals [1073741824,2147483647] and [-1073741824,-1]
|
||||||
|
DEBUG: join prunable for intervals [1073741824,2147483647] and [0,1073741823]
|
||||||
DEBUG: generating subplan 108_1 for subquery SELECT sum(raw_events_second.value_4) AS v4, raw_events_second.value_1 AS v1, sum(raw_events_second.user_id) AS id FROM public.raw_events_first, public.raw_events_second WHERE (raw_events_first.user_id = raw_events_second.user_id) GROUP BY raw_events_second.value_1 HAVING (sum(raw_events_second.value_4) > (10)::numeric)
|
DEBUG: generating subplan 108_1 for subquery SELECT sum(raw_events_second.value_4) AS v4, raw_events_second.value_1 AS v1, sum(raw_events_second.user_id) AS id FROM public.raw_events_first, public.raw_events_second WHERE (raw_events_first.user_id = raw_events_second.user_id) GROUP BY raw_events_second.value_1 HAVING (sum(raw_events_second.value_4) > (10)::numeric)
|
||||||
-- cannot pushdown the query since the JOIN is not equi JOIN
|
-- cannot pushdown the query since the JOIN is not equi JOIN
|
||||||
INSERT INTO agg_events
|
INSERT INTO agg_events
|
||||||
|
@ -1630,8 +1663,8 @@ HINT: Consider using an equality filter on the distributed table's partition co
|
||||||
SET client_min_messages TO INFO;
|
SET client_min_messages TO INFO;
|
||||||
-- avoid constraint violations
|
-- avoid constraint violations
|
||||||
TRUNCATE raw_events_first;
|
TRUNCATE raw_events_first;
|
||||||
-- we don't support LIMIT even if it exists in the subqueries
|
-- we don't support LIMIT for subquery pushdown, but
|
||||||
-- in where clause
|
-- we recursively plan the query and run it via coordinator
|
||||||
INSERT INTO agg_events(user_id)
|
INSERT INTO agg_events(user_id)
|
||||||
SELECT user_id
|
SELECT user_id
|
||||||
FROM users_table
|
FROM users_table
|
||||||
|
@ -1653,8 +1686,6 @@ WHERE user_id
|
||||||
) as f_inner
|
) as f_inner
|
||||||
)
|
)
|
||||||
) AS f2);
|
) AS f2);
|
||||||
ERROR: cannot push down this subquery
|
|
||||||
DETAIL: Limit in subquery is currently unsupported
|
|
||||||
-- Altering a table and selecting from it using a multi-shard statement
|
-- Altering a table and selecting from it using a multi-shard statement
|
||||||
-- in the same transaction is allowed because we will use the same
|
-- in the same transaction is allowed because we will use the same
|
||||||
-- connections for all co-located placements.
|
-- connections for all co-located placements.
|
||||||
|
|
|
@ -676,7 +676,7 @@ FROM
|
||||||
WHERE users_table.value_1 < 50;
|
WHERE users_table.value_1 < 50;
|
||||||
ERROR: cannot perform distributed planning for the given modification
|
ERROR: cannot perform distributed planning for the given modification
|
||||||
DETAIL: Select query cannot be pushed down to the worker.
|
DETAIL: Select query cannot be pushed down to the worker.
|
||||||
-- not supported since one of the queries doesn't have a relation
|
-- supported via recursive planning
|
||||||
INSERT INTO agg_results (user_id, agg_time, value_2_agg)
|
INSERT INTO agg_results (user_id, agg_time, value_2_agg)
|
||||||
SELECT
|
SELECT
|
||||||
user_id,
|
user_id,
|
||||||
|
@ -702,5 +702,3 @@ FROM (
|
||||||
GROUP BY user_id
|
GROUP BY user_id
|
||||||
) AS shard_union
|
) AS shard_union
|
||||||
ORDER BY user_lastseen DESC;
|
ORDER BY user_lastseen DESC;
|
||||||
ERROR: cannot push down this subquery
|
|
||||||
DETAIL: Subqueries without a FROM clause can only contain immutable functions
|
|
||||||
|
|
|
@ -508,6 +508,7 @@ HINT: Set citus.enable_repartition_joins to on to enable repartitioning
|
||||||
-- subqueries are not supported in SELECT clause
|
-- subqueries are not supported in SELECT clause
|
||||||
SELECT a.title AS name, (SELECT a2.id FROM articles_single_shard_hash_mx a2 WHERE a.id = a2.id LIMIT 1)
|
SELECT a.title AS name, (SELECT a2.id FROM articles_single_shard_hash_mx a2 WHERE a.id = a2.id LIMIT 1)
|
||||||
AS special_price FROM articles_hash_mx a;
|
AS special_price FROM articles_hash_mx a;
|
||||||
|
DEBUG: skipping recursive planning for the subquery since it contains references to outer queries
|
||||||
ERROR: could not run distributed query with subquery outside the FROM and WHERE clauses
|
ERROR: could not run distributed query with subquery outside the FROM and WHERE clauses
|
||||||
HINT: Consider using an equality filter on the distributed table's partition column.
|
HINT: Consider using an equality filter on the distributed table's partition column.
|
||||||
-- simple lookup query
|
-- simple lookup query
|
||||||
|
|
|
@ -51,6 +51,29 @@ SELECT a FROM dest_table;
|
||||||
2
|
2
|
||||||
(2 rows)
|
(2 rows)
|
||||||
|
|
||||||
|
-- subqueries are also allowed
|
||||||
|
SET client_min_messages TO DEBUG1;
|
||||||
|
SELECT
|
||||||
|
foo.a
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
WITH cte AS (
|
||||||
|
SELECT
|
||||||
|
DISTINCT dest_table.a
|
||||||
|
FROM
|
||||||
|
dest_table, source_table
|
||||||
|
WHERE
|
||||||
|
source_table.a = dest_table.a AND
|
||||||
|
dest_table.b IN (1,2,3,4)
|
||||||
|
) SELECT * FROM cte ORDER BY 1 DESC LIMIT 5
|
||||||
|
) as foo;
|
||||||
|
DEBUG: generating subplan 4_1 for CTE cte: SELECT DISTINCT dest_table.a FROM public.dest_table, public.source_table WHERE ((source_table.a = dest_table.a) AND (dest_table.b = ANY (ARRAY[1, 2, 3, 4])))
|
||||||
|
DEBUG: generating subplan 4_2 for subquery SELECT a FROM (SELECT intermediate_result.a FROM read_intermediate_result('4_1'::text, 'binary'::citus_copy_format) intermediate_result(a integer)) cte ORDER BY a DESC LIMIT 5
|
||||||
|
a
|
||||||
|
---
|
||||||
|
(0 rows)
|
||||||
|
|
||||||
|
SET client_min_messages TO DEFAULT;
|
||||||
-- insert into is definitely not allowed
|
-- insert into is definitely not allowed
|
||||||
INSERT INTO dest_table (a, b)
|
INSERT INTO dest_table (a, b)
|
||||||
SELECT a, b FROM source_table;
|
SELECT a, b FROM source_table;
|
||||||
|
|
|
@ -623,6 +623,7 @@ HINT: Set citus.enable_repartition_joins to on to enable repartitioning
|
||||||
-- subqueries are not supported in SELECT clause
|
-- subqueries are not supported in SELECT clause
|
||||||
SELECT a.title AS name, (SELECT a2.id FROM articles_single_shard_hash a2 WHERE a.id = a2.id LIMIT 1)
|
SELECT a.title AS name, (SELECT a2.id FROM articles_single_shard_hash a2 WHERE a.id = a2.id LIMIT 1)
|
||||||
AS special_price FROM articles_hash a;
|
AS special_price FROM articles_hash a;
|
||||||
|
DEBUG: skipping recursive planning for the subquery since it contains references to outer queries
|
||||||
ERROR: could not run distributed query with subquery outside the FROM and WHERE clauses
|
ERROR: could not run distributed query with subquery outside the FROM and WHERE clauses
|
||||||
HINT: Consider using an equality filter on the distributed table's partition column.
|
HINT: Consider using an equality filter on the distributed table's partition column.
|
||||||
-- simple lookup query
|
-- simple lookup query
|
||||||
|
|
|
@ -195,8 +195,12 @@ SELECT * FROM articles, position('om' in 'Thomas') ORDER BY 2 DESC, 1 DESC, 3 DE
|
||||||
10 | 10 | aggrandize | 17277 | 3
|
10 | 10 | aggrandize | 17277 | 3
|
||||||
(5 rows)
|
(5 rows)
|
||||||
|
|
||||||
|
-- subqueries are supported in WHERE clause in Citus even if the relations are not distributed
|
||||||
SELECT * FROM articles WHERE author_id IN (SELECT id FROM authors WHERE name LIKE '%a');
|
SELECT * FROM articles WHERE author_id IN (SELECT id FROM authors WHERE name LIKE '%a');
|
||||||
ERROR: relation authors is not distributed
|
id | author_id | title | word_count
|
||||||
|
----+-----------+-------+------------
|
||||||
|
(0 rows)
|
||||||
|
|
||||||
-- subqueries are supported in FROM clause
|
-- subqueries are supported in FROM clause
|
||||||
SELECT articles.id,test.word_count
|
SELECT articles.id,test.word_count
|
||||||
FROM articles, (SELECT id, word_count FROM articles) AS test WHERE test.id = articles.id
|
FROM articles, (SELECT id, word_count FROM articles) AS test WHERE test.id = articles.id
|
||||||
|
|
|
@ -28,8 +28,7 @@ SET
|
||||||
shardmaxvalue = '14947'
|
shardmaxvalue = '14947'
|
||||||
WHERE
|
WHERE
|
||||||
shardid IN (SELECT shardid FROM pg_dist_shard WHERE logicalrelid = 'orders_subquery'::regclass ORDER BY shardid DESC LIMIT 1);
|
shardid IN (SELECT shardid FROM pg_dist_shard WHERE logicalrelid = 'orders_subquery'::regclass ORDER BY shardid DESC LIMIT 1);
|
||||||
-- If group by is not on partition column then we error out from single table
|
-- If group by is not on partition column then we recursively plan
|
||||||
-- repartition code path
|
|
||||||
SELECT
|
SELECT
|
||||||
avg(order_count)
|
avg(order_count)
|
||||||
FROM
|
FROM
|
||||||
|
@ -40,8 +39,7 @@ FROM
|
||||||
lineitem_subquery
|
lineitem_subquery
|
||||||
GROUP BY
|
GROUP BY
|
||||||
l_suppkey) AS order_counts;
|
l_suppkey) AS order_counts;
|
||||||
ERROR: the query contains a join that requires repartitioning
|
ERROR: cannot handle complex subqueries when the router executor is disabled
|
||||||
HINT: Set citus.enable_repartition_joins to on to enable repartitioning
|
|
||||||
-- Check that we error out if join is not on partition columns.
|
-- Check that we error out if join is not on partition columns.
|
||||||
SELECT
|
SELECT
|
||||||
avg(unit_price)
|
avg(unit_price)
|
||||||
|
@ -71,12 +69,15 @@ FROM
|
||||||
l_orderkey) AS unit_prices;
|
l_orderkey) AS unit_prices;
|
||||||
ERROR: cannot pushdown the subquery since all relations are not joined using distribution keys
|
ERROR: cannot pushdown the subquery since all relations are not joined using distribution keys
|
||||||
DETAIL: Each relation should be joined with at least one another relation using distribution keys and equality operator.
|
DETAIL: Each relation should be joined with at least one another relation using distribution keys and equality operator.
|
||||||
-- Subqueries without relation with a volatile functions (non-constant)
|
-- Subqueries without relation with a volatile functions (non-constant) are planned recursively
|
||||||
SELECT count(*) FROM (
|
SELECT count(*) FROM (
|
||||||
SELECT l_orderkey FROM lineitem_subquery JOIN (SELECT random()::int r) sub ON (l_orderkey = r)
|
SELECT l_orderkey FROM lineitem_subquery JOIN (SELECT random()::int r) sub ON (l_orderkey = r) WHERE r > 10
|
||||||
) b;
|
) b;
|
||||||
ERROR: cannot push down this subquery
|
count
|
||||||
DETAIL: Subqueries without a FROM clause can only contain immutable functions
|
-------
|
||||||
|
0
|
||||||
|
(1 row)
|
||||||
|
|
||||||
-- Check that we error out if there is non relation subqueries
|
-- Check that we error out if there is non relation subqueries
|
||||||
SELECT count(*) FROM
|
SELECT count(*) FROM
|
||||||
(
|
(
|
||||||
|
@ -103,7 +104,8 @@ SELECT count(*) FROM
|
||||||
2985
|
2985
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
-- Check that we error out if inner query has Limit but subquery_pushdown is not set
|
-- we'd error out if inner query has Limit but subquery_pushdown is not set
|
||||||
|
-- but we recursively plan the query
|
||||||
SELECT
|
SELECT
|
||||||
avg(o_totalprice/l_quantity)
|
avg(o_totalprice/l_quantity)
|
||||||
FROM
|
FROM
|
||||||
|
@ -123,8 +125,11 @@ FROM
|
||||||
orders_subquery
|
orders_subquery
|
||||||
WHERE
|
WHERE
|
||||||
lineitem_quantities.l_orderkey = o_orderkey) orders_price ON true;
|
lineitem_quantities.l_orderkey = o_orderkey) orders_price ON true;
|
||||||
ERROR: cannot push down this subquery
|
avg
|
||||||
DETAIL: Limit in subquery is currently unsupported
|
-------------------------
|
||||||
|
129027.1270000000000000
|
||||||
|
(1 row)
|
||||||
|
|
||||||
-- Limit is only supported when subquery_pushdown is set
|
-- Limit is only supported when subquery_pushdown is set
|
||||||
-- Check that we error out if inner query has limit but outer query has not.
|
-- Check that we error out if inner query has limit but outer query has not.
|
||||||
SET citus.subquery_pushdown to ON;
|
SET citus.subquery_pushdown to ON;
|
||||||
|
|
|
@ -1185,7 +1185,9 @@ limit 50;
|
||||||
|
|
||||||
-- reset subquery_pushdown
|
-- reset subquery_pushdown
|
||||||
SET citus.subquery_pushdown to OFF;
|
SET citus.subquery_pushdown to OFF;
|
||||||
-- not supported since JOIN is not on the partition key
|
-- we recursively plan recent_events_1
|
||||||
|
-- but not some_users_data since it has a reference
|
||||||
|
-- from an outer query which is not recursively planned
|
||||||
SELECT "some_users_data".user_id, lastseen
|
SELECT "some_users_data".user_id, lastseen
|
||||||
FROM
|
FROM
|
||||||
(SELECT user_id, max(time) AS lastseen
|
(SELECT user_id, max(time) AS lastseen
|
||||||
|
@ -1218,10 +1220,11 @@ FROM
|
||||||
ORDER BY
|
ORDER BY
|
||||||
user_id
|
user_id
|
||||||
limit 50;
|
limit 50;
|
||||||
ERROR: cannot pushdown the subquery since all relations are not joined using distribution keys
|
ERROR: cannot push down this subquery
|
||||||
DETAIL: Each relation should be joined with at least one another relation using distribution keys and equality operator.
|
DETAIL: Limit in subquery is currently unsupported
|
||||||
-- not supported since JOIN is not on the partition key
|
-- we recursively plan some queries but fail in the end
|
||||||
-- see (2 * user_id as user_id) target list element
|
-- since some_users_data since it has a reference
|
||||||
|
-- from an outer query which is not recursively planned
|
||||||
SELECT "some_users_data".user_id, lastseen
|
SELECT "some_users_data".user_id, lastseen
|
||||||
FROM
|
FROM
|
||||||
(SELECT 2 * user_id as user_id, max(time) AS lastseen
|
(SELECT 2 * user_id as user_id, max(time) AS lastseen
|
||||||
|
@ -1254,8 +1257,8 @@ FROM
|
||||||
ORDER BY
|
ORDER BY
|
||||||
user_id
|
user_id
|
||||||
limit 50;
|
limit 50;
|
||||||
ERROR: cannot pushdown the subquery since all relations are not joined using distribution keys
|
ERROR: cannot push down this subquery
|
||||||
DETAIL: Each relation should be joined with at least one another relation using distribution keys and equality operator.
|
DETAIL: Limit in subquery is currently unsupported
|
||||||
-- LATERAL JOINs used with INNER JOINs
|
-- LATERAL JOINs used with INNER JOINs
|
||||||
SET citus.subquery_pushdown to ON;
|
SET citus.subquery_pushdown to ON;
|
||||||
SELECT user_id, lastseen
|
SELECT user_id, lastseen
|
||||||
|
@ -1550,7 +1553,9 @@ ORDER BY
|
||||||
LIMIT 10;
|
LIMIT 10;
|
||||||
ERROR: cannot pushdown the subquery since all relations are not joined using distribution keys
|
ERROR: cannot pushdown the subquery since all relations are not joined using distribution keys
|
||||||
DETAIL: Each relation should be joined with at least one another relation using distribution keys and equality operator.
|
DETAIL: Each relation should be joined with at least one another relation using distribution keys and equality operator.
|
||||||
-- not supported since lower LATERAL JOIN is not on the partition key
|
-- not pushdownable since lower LATERAL JOIN is not on the partition key
|
||||||
|
-- not recursively plannable due to LATERAL join where there is a reference
|
||||||
|
-- from an outer query
|
||||||
SELECT user_id, lastseen
|
SELECT user_id, lastseen
|
||||||
FROM
|
FROM
|
||||||
(SELECT
|
(SELECT
|
||||||
|
@ -1603,8 +1608,8 @@ FROM
|
||||||
ORDER BY
|
ORDER BY
|
||||||
user_id DESC
|
user_id DESC
|
||||||
LIMIT 10;
|
LIMIT 10;
|
||||||
ERROR: cannot pushdown the subquery since all relations are not joined using distribution keys
|
ERROR: cannot push down this subquery
|
||||||
DETAIL: Each relation should be joined with at least one another relation using distribution keys and equality operator.
|
DETAIL: Limit in subquery is currently unsupported
|
||||||
-- NESTED INNER JOINs
|
-- NESTED INNER JOINs
|
||||||
SELECT
|
SELECT
|
||||||
count(*) AS value, "generated_group_field"
|
count(*) AS value, "generated_group_field"
|
||||||
|
@ -2168,7 +2173,9 @@ LIMIT 10;
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
SET citus.subquery_pushdown to OFF;
|
SET citus.subquery_pushdown to OFF;
|
||||||
-- not supported since join is not on the partition key
|
-- not pushdownable since lower LATERAL JOIN is not on the partition key
|
||||||
|
-- not recursively plannable due to LATERAL join where there is a reference
|
||||||
|
-- from an outer query
|
||||||
SELECT *
|
SELECT *
|
||||||
FROM
|
FROM
|
||||||
(SELECT
|
(SELECT
|
||||||
|
@ -2206,8 +2213,8 @@ FROM
|
||||||
ORDER BY
|
ORDER BY
|
||||||
value_2 DESC, user_id DESC
|
value_2 DESC, user_id DESC
|
||||||
LIMIT 10;
|
LIMIT 10;
|
||||||
ERROR: cannot pushdown the subquery since all relations are not joined using distribution keys
|
ERROR: cannot push down this subquery
|
||||||
DETAIL: Each relation should be joined with at least one another relation using distribution keys and equality operator.
|
DETAIL: Limit in subquery is currently unsupported
|
||||||
-- lets test some unsupported set operations
|
-- lets test some unsupported set operations
|
||||||
-- not supported since we use INTERSECT
|
-- not supported since we use INTERSECT
|
||||||
SELECT ("final_query"."event_types") as types, count(*) AS sumOfEventType
|
SELECT ("final_query"."event_types") as types, count(*) AS sumOfEventType
|
||||||
|
|
|
@ -1203,15 +1203,16 @@ SELECT foo.user_id FROM
|
||||||
---------
|
---------
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
-- not supported since group by is on the reference table column
|
-- not pushdownable since group by is on the reference table column
|
||||||
|
-- recursively planned, but hits unsupported clause type error on the top level query
|
||||||
SELECT foo.user_id FROM
|
SELECT foo.user_id FROM
|
||||||
(
|
(
|
||||||
SELECT r.user_id, random() FROM users_table m JOIN events_reference_table r ON int4eq(m.user_id, r.user_id)
|
SELECT r.user_id, random() FROM users_table m JOIN events_reference_table r ON int4eq(m.user_id, r.user_id)
|
||||||
GROUP BY r.user_id
|
GROUP BY r.user_id
|
||||||
) as foo;
|
) as foo;
|
||||||
ERROR: cannot push down this subquery
|
ERROR: unsupported clause type
|
||||||
DETAIL: Group by list without partition column is currently unsupported
|
-- not pushdownable since the group by contains at least one distributed table
|
||||||
-- supported since the group by contains at least one distributed table
|
-- recursively planned, but hits unsupported clause type error on the top level query
|
||||||
SELECT foo.user_id FROM
|
SELECT foo.user_id FROM
|
||||||
(
|
(
|
||||||
SELECT r.user_id, random() FROM users_table m JOIN events_reference_table r ON int4eq(m.user_id, r.user_id)
|
SELECT r.user_id, random() FROM users_table m JOIN events_reference_table r ON int4eq(m.user_id, r.user_id)
|
||||||
|
@ -1225,20 +1226,19 @@ ORDER BY 1 LIMIT 3;
|
||||||
3
|
3
|
||||||
(3 rows)
|
(3 rows)
|
||||||
|
|
||||||
-- not supported since distinct is on the reference table column
|
-- not pushdownable since distinct is on the reference table column
|
||||||
|
-- recursively planned, but hits unsupported clause type error on the top level query
|
||||||
SELECT foo.user_id FROM
|
SELECT foo.user_id FROM
|
||||||
(
|
(
|
||||||
SELECT DISTINCT r.user_id, random() FROM users_table m JOIN events_reference_table r ON int4eq(m.user_id, r.user_id)
|
SELECT DISTINCT r.user_id, random() FROM users_table m JOIN events_reference_table r ON int4eq(m.user_id, r.user_id)
|
||||||
) as foo;
|
) as foo;
|
||||||
ERROR: cannot push down this subquery
|
ERROR: unsupported clause type
|
||||||
DETAIL: Distinct on columns without partition column is currently unsupported
|
|
||||||
-- not supported since distinct on is on the reference table column
|
-- not supported since distinct on is on the reference table column
|
||||||
SELECT foo.user_id FROM
|
SELECT foo.user_id FROM
|
||||||
(
|
(
|
||||||
SELECT DISTINCT ON(r.user_id) r.user_id, random() FROM users_table m JOIN events_reference_table r ON int4eq(m.user_id, r.user_id)
|
SELECT DISTINCT ON(r.user_id) r.user_id, random() FROM users_table m JOIN events_reference_table r ON int4eq(m.user_id, r.user_id)
|
||||||
) as foo;
|
) as foo;
|
||||||
ERROR: cannot push down this subquery
|
ERROR: unsupported clause type
|
||||||
DETAIL: Distinct on columns without partition column is currently unsupported
|
|
||||||
-- supported since the distinct on contains at least one distributed table
|
-- supported since the distinct on contains at least one distributed table
|
||||||
SELECT foo.user_id FROM
|
SELECT foo.user_id FROM
|
||||||
(
|
(
|
||||||
|
@ -1310,28 +1310,26 @@ OFFSET 0;
|
||||||
(5 rows)
|
(5 rows)
|
||||||
|
|
||||||
-- should not push down this query since there is a distributed table (i.e., events_table)
|
-- should not push down this query since there is a distributed table (i.e., events_table)
|
||||||
-- which is not in the DISTINCT clause
|
-- which is not in the DISTINCT clause. Recursive planning also fails since router execution
|
||||||
|
-- is disabled
|
||||||
SELECT * FROM
|
SELECT * FROM
|
||||||
(
|
(
|
||||||
SELECT DISTINCT users_reference_table.user_id FROM users_reference_table, events_table WHERE users_reference_table.user_id = events_table.value_4
|
SELECT DISTINCT users_reference_table.user_id FROM users_reference_table, events_table WHERE users_reference_table.user_id = events_table.value_4
|
||||||
) as foo;
|
) as foo;
|
||||||
ERROR: cannot push down this subquery
|
ERROR: cannot handle complex subqueries when the router executor is disabled
|
||||||
DETAIL: Distinct on columns without partition column is currently unsupported
|
|
||||||
SELECT * FROM
|
SELECT * FROM
|
||||||
(
|
(
|
||||||
SELECT users_reference_table.user_id FROM users_reference_table, events_table WHERE users_reference_table.user_id = events_table.value_4
|
SELECT users_reference_table.user_id FROM users_reference_table, events_table WHERE users_reference_table.user_id = events_table.value_4
|
||||||
GROUP BY 1
|
GROUP BY 1
|
||||||
) as foo;
|
) as foo;
|
||||||
ERROR: cannot push down this subquery
|
ERROR: cannot handle complex subqueries when the router executor is disabled
|
||||||
DETAIL: Group by list without partition column is currently unsupported
|
|
||||||
-- similiar to the above examples, this time there is a subquery
|
-- similiar to the above examples, this time there is a subquery
|
||||||
-- whose output is not in the DISTINCT clause
|
-- whose output is not in the DISTINCT clause
|
||||||
SELECT * FROM
|
SELECT * FROM
|
||||||
(
|
(
|
||||||
SELECT DISTINCT users_reference_table.user_id FROM users_reference_table, (SELECT user_id, random() FROM events_table) as us_events WHERE users_reference_table.user_id = us_events.user_id
|
SELECT DISTINCT users_reference_table.user_id FROM users_reference_table, (SELECT user_id, random() FROM events_table) as us_events WHERE users_reference_table.user_id = us_events.user_id
|
||||||
) as foo;
|
) as foo;
|
||||||
ERROR: cannot push down this subquery
|
ERROR: cannot handle complex subqueries when the router executor is disabled
|
||||||
DETAIL: Distinct on columns without partition column is currently unsupported
|
|
||||||
-- the following query is safe to push down since the DISTINCT clause include distribution column
|
-- the following query is safe to push down since the DISTINCT clause include distribution column
|
||||||
SELECT * FROM
|
SELECT * FROM
|
||||||
(
|
(
|
||||||
|
@ -1348,6 +1346,8 @@ LIMIT 4;
|
||||||
(4 rows)
|
(4 rows)
|
||||||
|
|
||||||
-- should not pushdown since there is a non partition column on the DISTINCT clause
|
-- should not pushdown since there is a non partition column on the DISTINCT clause
|
||||||
|
-- Recursive planning also fails since router execution
|
||||||
|
-- is disabled
|
||||||
SELECT * FROM
|
SELECT * FROM
|
||||||
(
|
(
|
||||||
SELECT
|
SELECT
|
||||||
|
@ -1360,8 +1360,7 @@ SELECT * FROM
|
||||||
) as foo
|
) as foo
|
||||||
ORDER BY 1 DESC
|
ORDER BY 1 DESC
|
||||||
LIMIT 4;
|
LIMIT 4;
|
||||||
ERROR: cannot push down this subquery
|
ERROR: cannot handle complex subqueries when the router executor is disabled
|
||||||
DETAIL: Distinct on columns without partition column is currently unsupported
|
|
||||||
-- test the read_intermediate_result() for GROUP BYs
|
-- test the read_intermediate_result() for GROUP BYs
|
||||||
BEGIN;
|
BEGIN;
|
||||||
|
|
||||||
|
|
|
@ -582,17 +582,20 @@ LIMIT 2;
|
||||||
(2 rows)
|
(2 rows)
|
||||||
|
|
||||||
-- subquery in where clause has a volatile function and no relation
|
-- subquery in where clause has a volatile function and no relation
|
||||||
|
-- thus we recursively plan it
|
||||||
SELECT
|
SELECT
|
||||||
user_id
|
user_id
|
||||||
FROM
|
FROM
|
||||||
users_table
|
users_table
|
||||||
WHERE
|
WHERE
|
||||||
value_2 >
|
value_2 >
|
||||||
(SELECT random())
|
(SELECT random()) AND user_id < 0
|
||||||
ORDER BY 1 ASC
|
ORDER BY 1 ASC
|
||||||
LIMIT 2;
|
LIMIT 2;
|
||||||
ERROR: cannot push down this subquery
|
user_id
|
||||||
DETAIL: Subqueries without a FROM clause can only contain immutable functions
|
---------
|
||||||
|
(0 rows)
|
||||||
|
|
||||||
-- OFFSET is not supported in the subquey
|
-- OFFSET is not supported in the subquey
|
||||||
SELECT
|
SELECT
|
||||||
user_id
|
user_id
|
||||||
|
@ -614,7 +617,8 @@ ERROR: cannot push down this subquery
|
||||||
DETAIL: Offset clause is currently unsupported
|
DETAIL: Offset clause is currently unsupported
|
||||||
-- we can detect unsupported subquerues even if they appear
|
-- we can detect unsupported subquerues even if they appear
|
||||||
-- in WHERE subquery -> FROM subquery -> WHERE subquery
|
-- in WHERE subquery -> FROM subquery -> WHERE subquery
|
||||||
SELECT user_id
|
-- but we can recursively plan that anyway
|
||||||
|
SELECT DISTINCT user_id
|
||||||
FROM users_table
|
FROM users_table
|
||||||
WHERE user_id
|
WHERE user_id
|
||||||
IN (SELECT
|
IN (SELECT
|
||||||
|
@ -638,9 +642,13 @@ WHERE user_id
|
||||||
AND e1.user_id IN (SELECT user_id FROM users_table LIMIT 3 )
|
AND e1.user_id IN (SELECT user_id FROM users_table LIMIT 3 )
|
||||||
) as f_outer
|
) as f_outer
|
||||||
WHERE f_inner.user_id = f_outer.user_id
|
WHERE f_inner.user_id = f_outer.user_id
|
||||||
);
|
) ORDER BY 1 LIMIT 3;
|
||||||
ERROR: cannot push down this subquery
|
user_id
|
||||||
DETAIL: Limit in subquery is currently unsupported
|
---------
|
||||||
|
1
|
||||||
|
5
|
||||||
|
(2 rows)
|
||||||
|
|
||||||
-- semi join is not on the partition key for the third subquery
|
-- semi join is not on the partition key for the third subquery
|
||||||
SELECT user_id
|
SELECT user_id
|
||||||
FROM users_table
|
FROM users_table
|
||||||
|
|
|
@ -739,6 +739,8 @@ LIMIT 5;
|
||||||
|
|
||||||
-- now lets also have some unsupported queries
|
-- now lets also have some unsupported queries
|
||||||
-- group by is not on the partition key
|
-- group by is not on the partition key
|
||||||
|
-- but we can still recursively plan it, though that is not suffient for pushdown
|
||||||
|
-- of the whole query
|
||||||
SELECT user_id, sum(counter)
|
SELECT user_id, sum(counter)
|
||||||
FROM (
|
FROM (
|
||||||
SELECT user_id, sum(value_2) AS counter FROM events_table GROUP BY user_id
|
SELECT user_id, sum(value_2) AS counter FROM events_table GROUP BY user_id
|
||||||
|
@ -1030,7 +1032,9 @@ FROM
|
||||||
) b;
|
) b;
|
||||||
ERROR: cannot pushdown the subquery since not all subqueries in the UNION have the partition column in the same position
|
ERROR: cannot pushdown the subquery since not all subqueries in the UNION have the partition column in the same position
|
||||||
DETAIL: Each leaf query of the UNION should return the partition column in the same position and all joins must be on the partition column
|
DETAIL: Each leaf query of the UNION should return the partition column in the same position and all joins must be on the partition column
|
||||||
-- we don't support subqueries without relations
|
-- we don't support pushing down subqueries without relations
|
||||||
|
-- recursive planning can replace that query, though the whole
|
||||||
|
-- query is not safe to pushdown
|
||||||
SELECT
|
SELECT
|
||||||
count(*)
|
count(*)
|
||||||
FROM
|
FROM
|
||||||
|
@ -1041,7 +1045,9 @@ FROM
|
||||||
) b;
|
) b;
|
||||||
ERROR: could not run distributed query with UNION, INTERSECT, or EXCEPT
|
ERROR: could not run distributed query with UNION, INTERSECT, or EXCEPT
|
||||||
HINT: Consider using an equality filter on the distributed table's partition column.
|
HINT: Consider using an equality filter on the distributed table's partition column.
|
||||||
-- we don't support subqueries without relations
|
-- we don't support pushing down subqueries without relations
|
||||||
|
-- recursive planning can replace that query, though the whole
|
||||||
|
-- query is not safe to pushdown
|
||||||
SELECT
|
SELECT
|
||||||
*
|
*
|
||||||
FROM
|
FROM
|
||||||
|
@ -1073,6 +1079,9 @@ ORDER BY 1 DESC, 2 DESC
|
||||||
LIMIT 5;
|
LIMIT 5;
|
||||||
ERROR: could not run distributed query with UNION, INTERSECT, or EXCEPT
|
ERROR: could not run distributed query with UNION, INTERSECT, or EXCEPT
|
||||||
HINT: Consider using an equality filter on the distributed table's partition column.
|
HINT: Consider using an equality filter on the distributed table's partition column.
|
||||||
|
-- we don't support pushing down subqueries without relations
|
||||||
|
-- recursive planning can replace that query, though the whole
|
||||||
|
-- query is not safe to pushdown
|
||||||
SELECT ("final_query"."event_types") as types, count(*) AS sumOfEventType
|
SELECT ("final_query"."event_types") as types, count(*) AS sumOfEventType
|
||||||
FROM
|
FROM
|
||||||
( SELECT *, random()
|
( SELECT *, random()
|
||||||
|
|
|
@ -287,9 +287,17 @@ SET citus.task_executor_type to DEFAULT;
|
||||||
-- create a view with aggregate
|
-- create a view with aggregate
|
||||||
CREATE VIEW lineitems_by_shipping_method AS
|
CREATE VIEW lineitems_by_shipping_method AS
|
||||||
SELECT l_shipmode, count(*) as cnt FROM lineitem_hash_part GROUP BY 1;
|
SELECT l_shipmode, count(*) as cnt FROM lineitem_hash_part GROUP BY 1;
|
||||||
-- following will fail due to non GROUP BY of partition key
|
-- following will be supported via recursive planning
|
||||||
SELECT * FROM lineitems_by_shipping_method;
|
SELECT * FROM lineitems_by_shipping_method ORDER BY 1,2 LIMIT 5;
|
||||||
ERROR: Unrecognized range table id 1
|
l_shipmode | cnt
|
||||||
|
------------+------
|
||||||
|
AIR | 1706
|
||||||
|
FOB | 1709
|
||||||
|
MAIL | 1739
|
||||||
|
RAIL | 1706
|
||||||
|
REG AIR | 1679
|
||||||
|
(5 rows)
|
||||||
|
|
||||||
-- create a view with group by on partition column
|
-- create a view with group by on partition column
|
||||||
CREATE VIEW lineitems_by_orderkey AS
|
CREATE VIEW lineitems_by_orderkey AS
|
||||||
SELECT
|
SELECT
|
||||||
|
@ -631,21 +639,39 @@ SELECT * FROM distinct_user_with_value_1_3 ORDER BY user_id;
|
||||||
(6 rows)
|
(6 rows)
|
||||||
|
|
||||||
-- distinct is not supported if it is on a non-partition key
|
-- distinct is not supported if it is on a non-partition key
|
||||||
|
-- but will be supported via recursive planning
|
||||||
CREATE VIEW distinct_value_1 AS SELECT DISTINCT value_1 FROM users_table WHERE value_2 = 3;
|
CREATE VIEW distinct_value_1 AS SELECT DISTINCT value_1 FROM users_table WHERE value_2 = 3;
|
||||||
SELECT * FROM distinct_value_1;
|
SELECT * FROM distinct_value_1 ORDER BY 1 DESC LIMIT 5;
|
||||||
ERROR: cannot perform distributed planning on this query
|
value_1
|
||||||
DETAIL: Subqueries without group by clause are not supported yet
|
---------
|
||||||
-- CTEs are not supported even if they are on views
|
5
|
||||||
|
4
|
||||||
|
3
|
||||||
|
2
|
||||||
|
1
|
||||||
|
(5 rows)
|
||||||
|
|
||||||
|
-- CTEs are supported even if they are on views
|
||||||
CREATE VIEW cte_view_1 AS
|
CREATE VIEW cte_view_1 AS
|
||||||
WITH c1 AS (SELECT * FROM users_table WHERE value_1 = 3) SELECT * FROM c1 WHERE value_2 < 4;
|
WITH c1 AS (SELECT * FROM users_table WHERE value_1 = 3) SELECT * FROM c1 WHERE value_2 < 4;
|
||||||
SELECT * FROM cte_view_1;
|
SELECT * FROM cte_view_1 ORDER BY 1,2,3,4,5 LIMIT 5;
|
||||||
ERROR: cannot push down this subquery
|
user_id | time | value_1 | value_2 | value_3 | value_4
|
||||||
DETAIL: CTEs in subqueries are currently unsupported
|
---------+---------------------------------+---------+---------+---------+---------
|
||||||
-- this is single shard query but still not supported since it has view + cte
|
1 | Thu Nov 23 03:32:50.803031 2017 | 3 | 2 | 1 |
|
||||||
|
2 | Thu Nov 23 13:52:54.83829 2017 | 3 | 1 | 4 |
|
||||||
|
3 | Wed Nov 22 23:24:32.080584 2017 | 3 | 2 | 5 |
|
||||||
|
4 | Wed Nov 22 23:59:46.493416 2017 | 3 | 1 | 3 |
|
||||||
|
4 | Thu Nov 23 01:55:21.824618 2017 | 3 | 1 | 4 |
|
||||||
|
(5 rows)
|
||||||
|
|
||||||
|
-- this is single shard query and still not supported since it has view + cte
|
||||||
-- router planner can't detect it
|
-- router planner can't detect it
|
||||||
SELECT * FROM cte_view_1 WHERE user_id = 2;
|
SELECT * FROM cte_view_1 WHERE user_id = 2 ORDER BY 1,2,3,4,5;
|
||||||
ERROR: cannot push down this subquery
|
user_id | time | value_1 | value_2 | value_3 | value_4
|
||||||
DETAIL: CTEs in subqueries are currently unsupported
|
---------+--------------------------------+---------+---------+---------+---------
|
||||||
|
2 | Thu Nov 23 13:52:54.83829 2017 | 3 | 1 | 4 |
|
||||||
|
(1 row)
|
||||||
|
|
||||||
-- if CTE itself prunes down to a single shard than the view is supported (router plannable)
|
-- if CTE itself prunes down to a single shard than the view is supported (router plannable)
|
||||||
CREATE VIEW cte_view_2 AS
|
CREATE VIEW cte_view_2 AS
|
||||||
WITH c1 AS (SELECT * FROM users_table WHERE user_id = 2) SELECT * FROM c1 WHERE value_1 = 3;
|
WITH c1 AS (SELECT * FROM users_table WHERE user_id = 2) SELECT * FROM c1 WHERE value_1 = 3;
|
||||||
|
@ -687,8 +713,16 @@ CREATE VIEW recent_10_users AS
|
||||||
LIMIT 10;
|
LIMIT 10;
|
||||||
-- this is not supported since it has limit in it and subquery_pushdown is not set
|
-- this is not supported since it has limit in it and subquery_pushdown is not set
|
||||||
SELECT * FROM recent_10_users;
|
SELECT * FROM recent_10_users;
|
||||||
ERROR: cannot perform distributed planning on this query
|
user_id | lastseen
|
||||||
DETAIL: Subqueries with limit are not supported yet
|
---------+---------------------------------
|
||||||
|
1 | Thu Nov 23 17:30:34.635085 2017
|
||||||
|
3 | Thu Nov 23 17:18:51.048758 2017
|
||||||
|
5 | Thu Nov 23 16:48:32.08896 2017
|
||||||
|
4 | Thu Nov 23 15:32:02.360969 2017
|
||||||
|
6 | Thu Nov 23 14:43:18.024104 2017
|
||||||
|
2 | Thu Nov 23 13:52:54.83829 2017
|
||||||
|
(6 rows)
|
||||||
|
|
||||||
SET citus.subquery_pushdown to ON;
|
SET citus.subquery_pushdown to ON;
|
||||||
-- still not supported since outer query does not have limit
|
-- still not supported since outer query does not have limit
|
||||||
-- it shows a different (subquery with single relation) error message
|
-- it shows a different (subquery with single relation) error message
|
||||||
|
@ -792,9 +826,43 @@ EXPLAIN (COSTS FALSE) SELECT *
|
||||||
(23 rows)
|
(23 rows)
|
||||||
|
|
||||||
EXPLAIN (COSTS FALSE) SELECT et.* FROM recent_10_users JOIN events_table et USING(user_id) ORDER BY et.time DESC LIMIT 10;
|
EXPLAIN (COSTS FALSE) SELECT et.* FROM recent_10_users JOIN events_table et USING(user_id) ORDER BY et.time DESC LIMIT 10;
|
||||||
ERROR: cannot push down this subquery
|
QUERY PLAN
|
||||||
DETAIL: Limit in subquery is currently unsupported
|
---------------------------------------------------------------------------------------------------------------------
|
||||||
|
Limit
|
||||||
|
-> Sort
|
||||||
|
Sort Key: remote_scan."time" DESC
|
||||||
|
-> Custom Scan (Citus Real-Time)
|
||||||
-> Distributed Subplan 83_1
|
-> Distributed Subplan 83_1
|
||||||
|
-> Limit
|
||||||
|
-> Sort
|
||||||
|
Sort Key: max((max(remote_scan.lastseen))) DESC
|
||||||
|
-> HashAggregate
|
||||||
|
Group Key: remote_scan.user_id
|
||||||
|
-> Custom Scan (Citus Real-Time)
|
||||||
|
Task Count: 4
|
||||||
|
Tasks Shown: One of 4
|
||||||
|
-> Task
|
||||||
|
Node: host=localhost port=57637 dbname=regression
|
||||||
|
-> Limit
|
||||||
|
-> Sort
|
||||||
|
Sort Key: (max("time")) DESC
|
||||||
|
-> HashAggregate
|
||||||
|
Group Key: user_id
|
||||||
|
-> Seq Scan on users_table_1400000 users_table
|
||||||
|
Task Count: 4
|
||||||
|
Tasks Shown: One of 4
|
||||||
|
-> Task
|
||||||
|
Node: host=localhost port=57637 dbname=regression
|
||||||
|
-> Limit
|
||||||
|
-> Sort
|
||||||
|
Sort Key: et."time" DESC
|
||||||
|
-> Hash Join
|
||||||
|
Hash Cond: (intermediate_result.user_id = et.user_id)
|
||||||
|
-> Function Scan on read_intermediate_result intermediate_result
|
||||||
|
-> Hash
|
||||||
|
-> Seq Scan on events_table_1400004 et
|
||||||
|
(33 rows)
|
||||||
|
|
||||||
SET citus.subquery_pushdown to ON;
|
SET citus.subquery_pushdown to ON;
|
||||||
EXPLAIN (COSTS FALSE) SELECT et.* FROM recent_10_users JOIN events_table et USING(user_id) ORDER BY et.time DESC LIMIT 10;
|
EXPLAIN (COSTS FALSE) SELECT et.* FROM recent_10_users JOIN events_table et USING(user_id) ORDER BY et.time DESC LIMIT 10;
|
||||||
QUERY PLAN
|
QUERY PLAN
|
||||||
|
|
|
@ -0,0 +1,194 @@
|
||||||
|
-- ===================================================================
|
||||||
|
-- test recursive planning functionality with subqueries and CTEs
|
||||||
|
-- ===================================================================
|
||||||
|
CREATE SCHEMA subquery_deep;
|
||||||
|
SET search_path TO subquery_and_ctes, public;
|
||||||
|
SET client_min_messages TO DEBUG1;
|
||||||
|
-- subquery in FROM -> FROM -> FROM should be replaced due to OFFSET
|
||||||
|
-- one level up subquery should be replaced due to GROUP BY on non partition key
|
||||||
|
-- one level up subquery should be replaced due to LIMUT
|
||||||
|
SELECT
|
||||||
|
DISTINCT user_id
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT users_table.user_id FROM users_table,
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
avg(event_type) as avg_val
|
||||||
|
FROM
|
||||||
|
(SELECT event_type, users_table.user_id FROM users_table,
|
||||||
|
(SELECT user_id, event_type FROM events_table WHERE value_2 < 3 OFFSET 3) as foo
|
||||||
|
WHERE foo.user_id = users_table.user_id
|
||||||
|
) bar, users_table WHERE bar.user_id = users_table.user_id GROUP BY users_table.value_1
|
||||||
|
) as baz
|
||||||
|
WHERE baz.avg_val < users_table.user_id
|
||||||
|
LIMIT 3
|
||||||
|
) as sub1
|
||||||
|
ORDER BY 1 DESC;
|
||||||
|
DEBUG: generating subplan 1_1 for subquery SELECT user_id, event_type FROM public.events_table WHERE (value_2 < 3) OFFSET 3
|
||||||
|
DEBUG: generating subplan 1_2 for subquery SELECT avg(bar.event_type) AS avg_val FROM (SELECT foo.event_type, users_table_1.user_id FROM public.users_table users_table_1, (SELECT intermediate_result.user_id, intermediate_result.event_type FROM read_intermediate_result('1_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer, event_type integer)) foo WHERE (foo.user_id = users_table_1.user_id)) bar, public.users_table WHERE (bar.user_id = users_table.user_id) GROUP BY users_table.value_1
|
||||||
|
DEBUG: push down of limit count: 3
|
||||||
|
DEBUG: generating subplan 1_3 for subquery SELECT users_table.user_id FROM public.users_table, (SELECT intermediate_result.avg_val FROM read_intermediate_result('1_2'::text, 'binary'::citus_copy_format) intermediate_result(avg_val numeric)) baz WHERE (baz.avg_val < (users_table.user_id)::numeric) LIMIT 3
|
||||||
|
user_id
|
||||||
|
---------
|
||||||
|
5
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- subquery in FROM -> FROM -> WHERE -> WHERE should be replaced due to CTE
|
||||||
|
-- subquery in FROM -> FROM -> WHERE should be replaced due to LIMIT
|
||||||
|
-- one level above should be replaced due to DISTINCT on non-partition key
|
||||||
|
-- one level above should be replaced due to GROUP BY on non-partition key
|
||||||
|
SELECT event, array_length(events_table, 1)
|
||||||
|
FROM (
|
||||||
|
SELECT event, array_agg(t.user_id) AS events_table
|
||||||
|
FROM (
|
||||||
|
SELECT
|
||||||
|
DISTINCT ON(e.event_type::text) e.event_type::text as event, e.time, e.user_id
|
||||||
|
FROM
|
||||||
|
users_table AS u,
|
||||||
|
events_table AS e
|
||||||
|
WHERE u.user_id = e.user_id AND
|
||||||
|
u.user_id IN
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
user_id
|
||||||
|
FROM
|
||||||
|
users_table
|
||||||
|
WHERE value_2 >= 5
|
||||||
|
AND EXISTS (SELECT user_id FROM events_table WHERE event_type > 1 AND event_type <= 3 AND value_3 > 1 AND user_id = users_table.user_id)
|
||||||
|
AND NOT EXISTS (SELECT user_id FROM events_table WHERE event_type > 3 AND event_type <= 4 AND value_3 > 1 AND user_id = users_table.user_id)
|
||||||
|
AND EXISTS (WITH cte AS (SELECT count(*) FROM users_table) SELECT * FROM cte)
|
||||||
|
LIMIT 5
|
||||||
|
)
|
||||||
|
) t, users_table WHERE users_table.value_1 = t.event::int
|
||||||
|
GROUP BY event
|
||||||
|
) q
|
||||||
|
ORDER BY 2 DESC, 1;
|
||||||
|
DEBUG: generating subplan 5_1 for CTE cte: SELECT count(*) AS count FROM public.users_table
|
||||||
|
DEBUG: push down of limit count: 5
|
||||||
|
DEBUG: generating subplan 5_2 for subquery SELECT user_id FROM public.users_table WHERE ((value_2 >= 5) AND (EXISTS (SELECT events_table.user_id FROM public.events_table WHERE ((events_table.event_type > 1) AND (events_table.event_type <= 3) AND (events_table.value_3 > (1)::double precision) AND (events_table.user_id = users_table.user_id)))) AND (NOT (EXISTS (SELECT events_table.user_id FROM public.events_table WHERE ((events_table.event_type > 3) AND (events_table.event_type <= 4) AND (events_table.value_3 > (1)::double precision) AND (events_table.user_id = users_table.user_id))))) AND (EXISTS (SELECT cte.count FROM (SELECT intermediate_result.count FROM read_intermediate_result('5_1'::text, 'binary'::citus_copy_format) intermediate_result(count bigint)) cte))) LIMIT 5
|
||||||
|
DEBUG: generating subplan 5_3 for subquery SELECT DISTINCT ON ((e.event_type)::text) (e.event_type)::text AS event, e."time", e.user_id FROM public.users_table u, public.events_table e WHERE ((u.user_id = e.user_id) AND (u.user_id IN (SELECT intermediate_result.user_id FROM read_intermediate_result('5_2'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer))))
|
||||||
|
DEBUG: generating subplan 5_4 for subquery SELECT t.event, array_agg(t.user_id) AS events_table FROM (SELECT intermediate_result.event, intermediate_result."time", intermediate_result.user_id FROM read_intermediate_result('5_3'::text, 'binary'::citus_copy_format) intermediate_result(event text, "time" timestamp without time zone, user_id integer)) t, public.users_table WHERE (users_table.value_1 = (t.event)::integer) GROUP BY t.event
|
||||||
|
event | array_length
|
||||||
|
-------+--------------
|
||||||
|
3 | 26
|
||||||
|
4 | 21
|
||||||
|
2 | 18
|
||||||
|
1 | 15
|
||||||
|
0 | 12
|
||||||
|
5 | 9
|
||||||
|
(6 rows)
|
||||||
|
|
||||||
|
-- this test probably doesn't add too much value,
|
||||||
|
-- but recurse 6 times for fun
|
||||||
|
SELECT count(*)
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT avg(min) FROM
|
||||||
|
(
|
||||||
|
SELECT min(users_table.value_1) FROM
|
||||||
|
(
|
||||||
|
SELECT avg(event_type) as avg_ev_type FROM
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
max(value_1) as mx_val_1
|
||||||
|
FROM (
|
||||||
|
SELECT
|
||||||
|
avg(event_type) as avg
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
cnt
|
||||||
|
FROM
|
||||||
|
(SELECT count(*) as cnt, value_2 FROM users_table GROUP BY value_2) as level_1, users_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = level_1.cnt
|
||||||
|
) as level_2, events_table
|
||||||
|
WHERE events_table.user_id = level_2.cnt
|
||||||
|
GROUP BY level_2.cnt
|
||||||
|
) as level_3, users_table
|
||||||
|
WHERE user_id = level_3.avg
|
||||||
|
GROUP BY level_3.avg
|
||||||
|
) as level_4, events_table
|
||||||
|
WHERE level_4.mx_val_1 = events_table.user_id
|
||||||
|
GROUP BY level_4.mx_val_1
|
||||||
|
) as level_5, users_table
|
||||||
|
WHERE
|
||||||
|
level_5.avg_ev_type = users_table.user_id
|
||||||
|
GROUP BY
|
||||||
|
level_5.avg_ev_type
|
||||||
|
) as level_6, users_table WHERE users_table.user_id = level_6.min
|
||||||
|
GROUP BY users_table.value_1
|
||||||
|
) as bar;
|
||||||
|
DEBUG: generating subplan 10_1 for subquery SELECT count(*) AS cnt, value_2 FROM public.users_table GROUP BY value_2
|
||||||
|
DEBUG: generating subplan 10_2 for subquery SELECT avg(events_table.event_type) AS avg FROM (SELECT level_1.cnt FROM (SELECT intermediate_result.cnt, intermediate_result.value_2 FROM read_intermediate_result('10_1'::text, 'binary'::citus_copy_format) intermediate_result(cnt bigint, value_2 integer)) level_1, public.users_table WHERE (users_table.user_id = level_1.cnt)) level_2, public.events_table WHERE (events_table.user_id = level_2.cnt) GROUP BY level_2.cnt
|
||||||
|
DEBUG: generating subplan 10_3 for subquery SELECT max(users_table.value_1) AS mx_val_1 FROM (SELECT intermediate_result.avg FROM read_intermediate_result('10_2'::text, 'binary'::citus_copy_format) intermediate_result(avg numeric)) level_3, public.users_table WHERE ((users_table.user_id)::numeric = level_3.avg) GROUP BY level_3.avg
|
||||||
|
DEBUG: generating subplan 10_4 for subquery SELECT avg(events_table.event_type) AS avg_ev_type FROM (SELECT intermediate_result.mx_val_1 FROM read_intermediate_result('10_3'::text, 'binary'::citus_copy_format) intermediate_result(mx_val_1 integer)) level_4, public.events_table WHERE (level_4.mx_val_1 = events_table.user_id) GROUP BY level_4.mx_val_1
|
||||||
|
DEBUG: generating subplan 10_5 for subquery SELECT min(users_table.value_1) AS min FROM (SELECT intermediate_result.avg_ev_type FROM read_intermediate_result('10_4'::text, 'binary'::citus_copy_format) intermediate_result(avg_ev_type numeric)) level_5, public.users_table WHERE (level_5.avg_ev_type = (users_table.user_id)::numeric) GROUP BY level_5.avg_ev_type
|
||||||
|
DEBUG: generating subplan 10_6 for subquery SELECT avg(level_6.min) AS avg FROM (SELECT intermediate_result.min FROM read_intermediate_result('10_5'::text, 'binary'::citus_copy_format) intermediate_result(min integer)) level_6, public.users_table WHERE (users_table.user_id = level_6.min) GROUP BY users_table.value_1
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
0
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- same query happening in the subqueries in WHERE
|
||||||
|
-- this test probably doesn't add too much value,
|
||||||
|
-- but recurse 6 times for fun
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
users_table
|
||||||
|
WHERE user_id IN (
|
||||||
|
SELECT count(*)
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT avg(min) FROM
|
||||||
|
(
|
||||||
|
SELECT min(users_table.value_1) FROM
|
||||||
|
(
|
||||||
|
SELECT avg(event_type) as avg_ev_type FROM
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
max(value_1) as mx_val_1
|
||||||
|
FROM (
|
||||||
|
SELECT
|
||||||
|
avg(event_type) as avg
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
cnt
|
||||||
|
FROM
|
||||||
|
(SELECT count(*) as cnt, value_2 FROM users_table GROUP BY value_2) as level_1, users_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = level_1.cnt
|
||||||
|
) as level_2, events_table
|
||||||
|
WHERE events_table.user_id = level_2.cnt
|
||||||
|
GROUP BY level_2.cnt
|
||||||
|
) as level_3, users_table
|
||||||
|
WHERE user_id = level_3.avg
|
||||||
|
GROUP BY level_3.avg
|
||||||
|
) as level_4, events_table
|
||||||
|
WHERE level_4.mx_val_1 = events_table.user_id
|
||||||
|
GROUP BY level_4.mx_val_1
|
||||||
|
) as level_5, users_table
|
||||||
|
WHERE
|
||||||
|
level_5.avg_ev_type = users_table.user_id
|
||||||
|
GROUP BY
|
||||||
|
level_5.avg_ev_type
|
||||||
|
) as level_6, users_table WHERE users_table.user_id = level_6.min
|
||||||
|
GROUP BY users_table.value_1
|
||||||
|
) as bar);
|
||||||
|
DEBUG: generating subplan 17_1 for subquery SELECT count(*) AS cnt, value_2 FROM public.users_table GROUP BY value_2
|
||||||
|
DEBUG: generating subplan 17_2 for subquery SELECT avg(events_table.event_type) AS avg FROM (SELECT level_1.cnt FROM (SELECT intermediate_result.cnt, intermediate_result.value_2 FROM read_intermediate_result('17_1'::text, 'binary'::citus_copy_format) intermediate_result(cnt bigint, value_2 integer)) level_1, public.users_table WHERE (users_table.user_id = level_1.cnt)) level_2, public.events_table WHERE (events_table.user_id = level_2.cnt) GROUP BY level_2.cnt
|
||||||
|
DEBUG: generating subplan 17_3 for subquery SELECT max(users_table.value_1) AS mx_val_1 FROM (SELECT intermediate_result.avg FROM read_intermediate_result('17_2'::text, 'binary'::citus_copy_format) intermediate_result(avg numeric)) level_3, public.users_table WHERE ((users_table.user_id)::numeric = level_3.avg) GROUP BY level_3.avg
|
||||||
|
DEBUG: generating subplan 17_4 for subquery SELECT avg(events_table.event_type) AS avg_ev_type FROM (SELECT intermediate_result.mx_val_1 FROM read_intermediate_result('17_3'::text, 'binary'::citus_copy_format) intermediate_result(mx_val_1 integer)) level_4, public.events_table WHERE (level_4.mx_val_1 = events_table.user_id) GROUP BY level_4.mx_val_1
|
||||||
|
DEBUG: generating subplan 17_5 for subquery SELECT min(users_table.value_1) AS min FROM (SELECT intermediate_result.avg_ev_type FROM read_intermediate_result('17_4'::text, 'binary'::citus_copy_format) intermediate_result(avg_ev_type numeric)) level_5, public.users_table WHERE (level_5.avg_ev_type = (users_table.user_id)::numeric) GROUP BY level_5.avg_ev_type
|
||||||
|
DEBUG: generating subplan 17_6 for subquery SELECT avg(level_6.min) AS avg FROM (SELECT intermediate_result.min FROM read_intermediate_result('17_5'::text, 'binary'::citus_copy_format) intermediate_result(min integer)) level_6, public.users_table WHERE (users_table.user_id = level_6.min) GROUP BY users_table.value_1
|
||||||
|
DEBUG: generating subplan 17_7 for subquery SELECT count(*) AS count FROM (SELECT intermediate_result.avg FROM read_intermediate_result('17_6'::text, 'binary'::citus_copy_format) intermediate_result(avg numeric)) bar
|
||||||
|
user_id | time | value_1 | value_2 | value_3 | value_4
|
||||||
|
---------+------+---------+---------+---------+---------
|
||||||
|
(0 rows)
|
||||||
|
|
||||||
|
SET client_min_messages TO DEFAULT;
|
||||||
|
DROP SCHEMA subquery_deep CASCADE;
|
||||||
|
SET search_path TO public;
|
|
@ -0,0 +1,147 @@
|
||||||
|
-- ===================================================================
|
||||||
|
-- test recursive planning functionality on failure cases
|
||||||
|
-- ===================================================================
|
||||||
|
CREATE SCHEMA not_supported;
|
||||||
|
SET search_path TO not_supported, public;
|
||||||
|
SET client_min_messages TO DEBUG1;
|
||||||
|
CREATE TABLE users_table_local AS SELECT * FROM users_table;
|
||||||
|
-- we don't support subqueries with local tables when they are not leaf queries
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
users_table_local.user_id
|
||||||
|
FROM
|
||||||
|
users_table_local, (SELECT user_id FROM events_table) as evs
|
||||||
|
WHERE users_table_local.user_id = evs.user_id
|
||||||
|
) as foo;
|
||||||
|
ERROR: relation users_table_local is not distributed
|
||||||
|
-- we don't support subqueries with local tables when they are not leaf queries
|
||||||
|
SELECT user_id FROM users_table WHERE user_id IN
|
||||||
|
(SELECT
|
||||||
|
user_id
|
||||||
|
FROM
|
||||||
|
users_table_local JOIN (SELECT user_id FROM events_table_local) as foo
|
||||||
|
USING (user_id)
|
||||||
|
);
|
||||||
|
ERROR: relation "events_table_local" does not exist
|
||||||
|
LINE 5: users_table_local JOIN (SELECT user_id FROM events_table_...
|
||||||
|
^
|
||||||
|
-- we don't support aggregate distinct if the group by is not on partition key, expect for count distinct
|
||||||
|
-- thus baz and bar are recursively planned but not foo
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT avg(DISTINCT value_1), random() FROM users_table GROUP BY user_id OFFSET 3
|
||||||
|
) as baz,
|
||||||
|
(
|
||||||
|
SELECT count(DISTINCT value_1), random() FROM users_table GROUP BY value_2 OFFSET 3
|
||||||
|
) as bar,
|
||||||
|
(
|
||||||
|
SELECT avg(DISTINCT value_1), random() FROM users_table GROUP BY value_2 OFFSET 3
|
||||||
|
) as foo;
|
||||||
|
DEBUG: generating subplan 4_1 for subquery SELECT avg(DISTINCT value_1) AS avg, random() AS random FROM public.users_table GROUP BY user_id OFFSET 3
|
||||||
|
DEBUG: generating subplan 4_2 for subquery SELECT count(DISTINCT value_1) AS count, random() AS random FROM public.users_table GROUP BY value_2 OFFSET 3
|
||||||
|
ERROR: cannot compute aggregate (distinct)
|
||||||
|
DETAIL: table partitioning is unsuitable for aggregate (distinct)
|
||||||
|
-- we don't support array_aggs with ORDER BYs
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
array_agg(users_table.user_id ORDER BY users_table.time)
|
||||||
|
FROM
|
||||||
|
users_table, (SELECT user_id FROM events_table) as evs
|
||||||
|
WHERE users_table.user_id = evs.user_id
|
||||||
|
GROUP BY users_table.user_id
|
||||||
|
LIMIT 5
|
||||||
|
) as foo;
|
||||||
|
ERROR: array_agg with order by is unsupported
|
||||||
|
-- we don't support queries with recurring tuples in the FROM
|
||||||
|
-- clause and subquery in WHERE clause
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
users_table.user_id
|
||||||
|
FROM
|
||||||
|
users_table, (SELECT user_id FROM events_table) as evs
|
||||||
|
WHERE users_table.user_id = evs.user_id
|
||||||
|
LIMIT 5
|
||||||
|
) as foo WHERE user_id IN (SELECT count(*) FROM users_table GROUP BY user_id);
|
||||||
|
DEBUG: push down of limit count: 5
|
||||||
|
DEBUG: generating subplan 10_1 for subquery SELECT users_table.user_id FROM public.users_table, (SELECT events_table.user_id FROM public.events_table) evs WHERE (users_table.user_id = evs.user_id) LIMIT 5
|
||||||
|
ERROR: cannot pushdown the subquery
|
||||||
|
DETAIL: Complex subqueries and CTEs are not allowed in the FROM clause when the query has subqueries in the WHERE clause
|
||||||
|
-- we don't support recursive subqueries when router executor is disabled
|
||||||
|
SET citus.enable_router_execution TO false;
|
||||||
|
SELECT
|
||||||
|
user_id
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
DISTINCT users_table.user_id
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
ORDER BY 1 DESC LIMIT 5
|
||||||
|
) as foo
|
||||||
|
ORDER BY 1 DESC;
|
||||||
|
DEBUG: push down of limit count: 5
|
||||||
|
DEBUG: generating subplan 12_1 for subquery SELECT DISTINCT users_table.user_id FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.user_id) AND (events_table.event_type = ANY (ARRAY[1, 2, 3, 4]))) ORDER BY users_table.user_id DESC LIMIT 5
|
||||||
|
ERROR: cannot handle complex subqueries when the router executor is disabled
|
||||||
|
SET citus.enable_router_execution TO true;
|
||||||
|
-- window functions are not allowed if they're not partitioned on the distribution column
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
user_id, time, rnk
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
*, rank() OVER my_win as rnk
|
||||||
|
FROM
|
||||||
|
events_table
|
||||||
|
WINDOW my_win AS (PARTITION BY event_type ORDER BY time DESC)
|
||||||
|
) as foo
|
||||||
|
ORDER BY
|
||||||
|
3 DESC, 1 DESC, 2 DESC
|
||||||
|
LIMIT
|
||||||
|
10) as foo;
|
||||||
|
ERROR: could not run distributed query because the window function that is used cannot be pushed down
|
||||||
|
HINT: Window functions are supported in two ways. Either add an equality filter on the distributed tables' partition column or use the window functions inside a subquery with a PARTITION BY clause containing the distribution column
|
||||||
|
-- top level join is not on the distribution key thus not supported
|
||||||
|
-- (use random to prevent Postgres to pull subqueries)
|
||||||
|
SELECT
|
||||||
|
foo.value_2
|
||||||
|
FROM
|
||||||
|
(SELECT users_table.value_2, random() FROM users_table, events_table WHERE users_table.user_id = events_table.user_id AND event_type IN (1,2,3,4)) as foo,
|
||||||
|
(SELECT users_table.value_2 FROM users_table, events_table WHERE users_table.user_id = events_table.user_id AND event_type IN (5,6,7,8)) as bar
|
||||||
|
WHERE
|
||||||
|
foo.value_2 = bar.value_2;
|
||||||
|
ERROR: cannot pushdown the subquery since all relations are not joined using distribution keys
|
||||||
|
DETAIL: Each relation should be joined with at least one another relation using distribution keys and equality operator.
|
||||||
|
-- OUTER JOINs where the outer part is recursively planned and not the other way
|
||||||
|
-- around is not supported
|
||||||
|
SELECT
|
||||||
|
foo.value_2
|
||||||
|
FROM
|
||||||
|
(SELECT users_table.value_2 FROM users_table, events_table WHERE users_table.user_id = events_table.user_id AND event_type IN (1,2,3,4) LIMIT 5) as foo
|
||||||
|
LEFT JOIN
|
||||||
|
(SELECT users_table.value_2 FROM users_table, events_table WHERE users_table.user_id = events_table.user_id AND event_type IN (5,6,7,8)) as bar
|
||||||
|
ON(foo.value_2 = bar.value_2);
|
||||||
|
DEBUG: push down of limit count: 5
|
||||||
|
DEBUG: generating subplan 17_1 for subquery SELECT users_table.value_2 FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.user_id) AND (events_table.event_type = ANY (ARRAY[1, 2, 3, 4]))) LIMIT 5
|
||||||
|
ERROR: cannot pushdown the subquery
|
||||||
|
DETAIL: Complex subqueries and CTEs cannot be in the outer part of the outer join
|
||||||
|
SET client_min_messages TO DEFAULT;
|
||||||
|
DROP SCHEMA not_supported CASCADE;
|
||||||
|
NOTICE: drop cascades to table users_table_local
|
||||||
|
SET search_path TO public;
|
|
@ -0,0 +1,422 @@
|
||||||
|
-- ===================================================================
|
||||||
|
-- test recursive planning functionality with subqueries and CTEs
|
||||||
|
-- ===================================================================
|
||||||
|
CREATE SCHEMA subquery_and_ctes;
|
||||||
|
SET search_path TO subquery_and_ctes, public;
|
||||||
|
CREATE TABLE users_table_local AS SELECT * FROM users_table;
|
||||||
|
SET client_min_messages TO DEBUG1;
|
||||||
|
-- CTEs are recursively planned, and subquery foo is also recursively planned
|
||||||
|
-- final plan becomes a router plan
|
||||||
|
WITH cte AS (
|
||||||
|
WITH local_cte AS (
|
||||||
|
SELECT * FROM users_table_local
|
||||||
|
),
|
||||||
|
dist_cte AS (
|
||||||
|
SELECT user_id FROM events_table
|
||||||
|
)
|
||||||
|
SELECT dist_cte.user_id FROM local_cte join dist_cte on dist_cte.user_id=local_cte.user_id
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
count(*)
|
||||||
|
FROM
|
||||||
|
cte,
|
||||||
|
(SELECT
|
||||||
|
DISTINCT users_table.user_id
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
ORDER BY 1 DESC LIMIT 5
|
||||||
|
) as foo
|
||||||
|
WHERE foo.user_id = cte.user_id;
|
||||||
|
DEBUG: generating subplan 2_1 for CTE cte: WITH local_cte AS (SELECT users_table_local.user_id, users_table_local."time", users_table_local.value_1, users_table_local.value_2, users_table_local.value_3, users_table_local.value_4 FROM subquery_and_ctes.users_table_local), dist_cte AS (SELECT events_table.user_id FROM public.events_table) SELECT dist_cte.user_id FROM (local_cte JOIN dist_cte ON ((dist_cte.user_id = local_cte.user_id)))
|
||||||
|
DEBUG: generating subplan 3_1 for CTE local_cte: SELECT user_id, "time", value_1, value_2, value_3, value_4 FROM subquery_and_ctes.users_table_local
|
||||||
|
DEBUG: generating subplan 3_2 for CTE dist_cte: SELECT user_id FROM public.events_table
|
||||||
|
DEBUG: push down of limit count: 5
|
||||||
|
DEBUG: generating subplan 2_2 for subquery SELECT DISTINCT users_table.user_id FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.user_id) AND (events_table.event_type = ANY (ARRAY[1, 2, 3, 4]))) ORDER BY users_table.user_id DESC LIMIT 5
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
1644
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- CTEs are recursively planned, and subquery foo is also recursively planned
|
||||||
|
-- final plan becomes a real-time plan since we also have events_table in the
|
||||||
|
-- range table entries
|
||||||
|
WITH cte AS (
|
||||||
|
WITH local_cte AS (
|
||||||
|
SELECT * FROM users_table_local
|
||||||
|
),
|
||||||
|
dist_cte AS (
|
||||||
|
SELECT user_id FROM events_table
|
||||||
|
)
|
||||||
|
SELECT dist_cte.user_id FROM local_cte join dist_cte on dist_cte.user_id=local_cte.user_id
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
count(*)
|
||||||
|
FROM
|
||||||
|
cte,
|
||||||
|
(SELECT
|
||||||
|
DISTINCT users_table.user_id
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
ORDER BY 1 DESC LIMIT 5
|
||||||
|
) as foo, events_table
|
||||||
|
WHERE foo.user_id = cte.user_id AND events_table.user_id = cte.user_id;
|
||||||
|
DEBUG: generating subplan 6_1 for CTE cte: WITH local_cte AS (SELECT users_table_local.user_id, users_table_local."time", users_table_local.value_1, users_table_local.value_2, users_table_local.value_3, users_table_local.value_4 FROM subquery_and_ctes.users_table_local), dist_cte AS (SELECT events_table.user_id FROM public.events_table) SELECT dist_cte.user_id FROM (local_cte JOIN dist_cte ON ((dist_cte.user_id = local_cte.user_id)))
|
||||||
|
DEBUG: generating subplan 7_1 for CTE local_cte: SELECT user_id, "time", value_1, value_2, value_3, value_4 FROM subquery_and_ctes.users_table_local
|
||||||
|
DEBUG: generating subplan 7_2 for CTE dist_cte: SELECT user_id FROM public.events_table
|
||||||
|
DEBUG: push down of limit count: 5
|
||||||
|
DEBUG: generating subplan 6_2 for subquery SELECT DISTINCT users_table.user_id FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.user_id) AND (events_table.event_type = ANY (ARRAY[1, 2, 3, 4]))) ORDER BY users_table.user_id DESC LIMIT 5
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
30608
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- CTEs are replaced and subquery in WHERE is also replaced
|
||||||
|
-- but the query is still real-time query since users_table is in the
|
||||||
|
-- range table list
|
||||||
|
WITH cte AS (
|
||||||
|
WITH local_cte AS (
|
||||||
|
SELECT * FROM users_table_local
|
||||||
|
),
|
||||||
|
dist_cte AS (
|
||||||
|
SELECT user_id FROM events_table
|
||||||
|
)
|
||||||
|
SELECT dist_cte.user_id FROM local_cte join dist_cte on dist_cte.user_id=local_cte.user_id
|
||||||
|
)
|
||||||
|
SELECT DISTINCT cte.user_id
|
||||||
|
FROM users_table, cte
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = cte.user_id AND
|
||||||
|
users_table.user_id IN (SELECT DISTINCT value_2 FROM users_table WHERE value_1 >= 1 AND value_1 <= 20 ORDER BY 1 LIMIT 5)
|
||||||
|
ORDER BY 1 DESC;
|
||||||
|
DEBUG: generating subplan 10_1 for CTE cte: WITH local_cte AS (SELECT users_table_local.user_id, users_table_local."time", users_table_local.value_1, users_table_local.value_2, users_table_local.value_3, users_table_local.value_4 FROM subquery_and_ctes.users_table_local), dist_cte AS (SELECT events_table.user_id FROM public.events_table) SELECT dist_cte.user_id FROM (local_cte JOIN dist_cte ON ((dist_cte.user_id = local_cte.user_id)))
|
||||||
|
DEBUG: generating subplan 11_1 for CTE local_cte: SELECT user_id, "time", value_1, value_2, value_3, value_4 FROM subquery_and_ctes.users_table_local
|
||||||
|
DEBUG: generating subplan 11_2 for CTE dist_cte: SELECT user_id FROM public.events_table
|
||||||
|
DEBUG: push down of limit count: 5
|
||||||
|
DEBUG: generating subplan 10_2 for subquery SELECT DISTINCT value_2 FROM public.users_table WHERE ((value_1 >= 1) AND (value_1 <= 20)) ORDER BY value_2 LIMIT 5
|
||||||
|
user_id
|
||||||
|
---------
|
||||||
|
4
|
||||||
|
3
|
||||||
|
2
|
||||||
|
1
|
||||||
|
(4 rows)
|
||||||
|
|
||||||
|
-- a very similar query as the above, but this time errors
|
||||||
|
-- out since we don't support subqueries in WHERE clause
|
||||||
|
-- when there is only intermediate results on the range table
|
||||||
|
-- note that this time subquery in WHERE clause is not replaced
|
||||||
|
WITH cte AS (
|
||||||
|
WITH local_cte AS (
|
||||||
|
SELECT * FROM users_table_local
|
||||||
|
),
|
||||||
|
dist_cte AS (
|
||||||
|
SELECT user_id FROM events_table
|
||||||
|
)
|
||||||
|
SELECT dist_cte.user_id FROM local_cte join dist_cte on dist_cte.user_id=local_cte.user_id
|
||||||
|
)
|
||||||
|
SELECT DISTINCT cte.user_id
|
||||||
|
FROM cte
|
||||||
|
WHERE
|
||||||
|
cte.user_id IN (SELECT DISTINCT user_id FROM users_table WHERE value_1 >= 1 AND value_1 <= 20)
|
||||||
|
ORDER BY 1 DESC;
|
||||||
|
DEBUG: generating subplan 14_1 for CTE cte: WITH local_cte AS (SELECT users_table_local.user_id, users_table_local."time", users_table_local.value_1, users_table_local.value_2, users_table_local.value_3, users_table_local.value_4 FROM subquery_and_ctes.users_table_local), dist_cte AS (SELECT events_table.user_id FROM public.events_table) SELECT dist_cte.user_id FROM (local_cte JOIN dist_cte ON ((dist_cte.user_id = local_cte.user_id)))
|
||||||
|
DEBUG: generating subplan 15_1 for CTE local_cte: SELECT user_id, "time", value_1, value_2, value_3, value_4 FROM subquery_and_ctes.users_table_local
|
||||||
|
DEBUG: generating subplan 15_2 for CTE dist_cte: SELECT user_id FROM public.events_table
|
||||||
|
ERROR: cannot pushdown the subquery
|
||||||
|
DETAIL: Complex subqueries and CTEs are not allowed in the FROM clause when the query has subqueries in the WHERE clause
|
||||||
|
-- CTEs inside a subquery and the final query becomes a router
|
||||||
|
-- query
|
||||||
|
SELECT
|
||||||
|
user_id
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
WITH cte AS (
|
||||||
|
SELECT
|
||||||
|
DISTINCT users_table.user_id
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
) SELECT * FROM cte ORDER BY 1 DESC
|
||||||
|
) as foo;
|
||||||
|
DEBUG: generating subplan 17_1 for CTE cte: SELECT DISTINCT users_table.user_id FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.user_id) AND (events_table.event_type = ANY (ARRAY[1, 2, 3, 4])))
|
||||||
|
user_id
|
||||||
|
---------
|
||||||
|
6
|
||||||
|
5
|
||||||
|
4
|
||||||
|
3
|
||||||
|
2
|
||||||
|
1
|
||||||
|
(6 rows)
|
||||||
|
|
||||||
|
-- CTEs inside a subquery and the final query becomes a
|
||||||
|
-- real-time query since the other subquery is safe to pushdown
|
||||||
|
SELECT
|
||||||
|
bar.user_id
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
WITH cte AS (
|
||||||
|
SELECT
|
||||||
|
DISTINCT users_table.user_id
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
) SELECT * FROM cte ORDER BY 1 DESC
|
||||||
|
) as foo,
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
DISTINCT users_table.user_id
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
|
||||||
|
) as bar
|
||||||
|
WHERE foo.user_id = bar.user_id;
|
||||||
|
DEBUG: generating subplan 19_1 for CTE cte: SELECT DISTINCT users_table.user_id FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.user_id) AND (events_table.event_type = ANY (ARRAY[1, 2, 3, 4])))
|
||||||
|
user_id
|
||||||
|
---------
|
||||||
|
5
|
||||||
|
1
|
||||||
|
4
|
||||||
|
3
|
||||||
|
6
|
||||||
|
2
|
||||||
|
(6 rows)
|
||||||
|
|
||||||
|
-- CTEs inside a deeper subquery
|
||||||
|
-- and also the subquery that contains the CTE is replaced
|
||||||
|
SELECT
|
||||||
|
DISTINCT bar.user_id
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
WITH cte AS (
|
||||||
|
SELECT
|
||||||
|
DISTINCT users_table.user_id
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
) SELECT * FROM cte ORDER BY 1 DESC
|
||||||
|
) as foo,
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
users_table.user_id, some_events.event_type
|
||||||
|
FROM
|
||||||
|
users_table,
|
||||||
|
(
|
||||||
|
WITH cte AS (
|
||||||
|
SELECT
|
||||||
|
event_type, users_table.user_id
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
value_1 IN (1,2)
|
||||||
|
) SELECT * FROM cte ORDER BY 1 DESC
|
||||||
|
) as some_events
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = some_events.user_id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
ORDER BY 2,1
|
||||||
|
LIMIT 2
|
||||||
|
|
||||||
|
) as bar
|
||||||
|
WHERE foo.user_id = bar.user_id
|
||||||
|
ORDER BY 1 DESC LIMIT 5;
|
||||||
|
DEBUG: generating subplan 21_1 for CTE cte: SELECT DISTINCT users_table.user_id FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.user_id) AND (events_table.event_type = ANY (ARRAY[1, 2, 3, 4])))
|
||||||
|
DEBUG: generating subplan 21_2 for CTE cte: SELECT events_table.event_type, users_table.user_id FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.user_id) AND (users_table.value_1 = ANY (ARRAY[1, 2])))
|
||||||
|
DEBUG: push down of limit count: 2
|
||||||
|
DEBUG: generating subplan 21_3 for subquery SELECT users_table.user_id, some_events.event_type FROM public.users_table, (SELECT cte.event_type, cte.user_id FROM (SELECT intermediate_result.event_type, intermediate_result.user_id FROM read_intermediate_result('21_2'::text, 'binary'::citus_copy_format) intermediate_result(event_type integer, user_id integer)) cte ORDER BY cte.event_type DESC) some_events WHERE ((users_table.user_id = some_events.user_id) AND (some_events.event_type = ANY (ARRAY[1, 2, 3, 4]))) ORDER BY some_events.event_type, users_table.user_id LIMIT 2
|
||||||
|
user_id
|
||||||
|
---------
|
||||||
|
1
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- CTEs on the different parts of the query is replaced
|
||||||
|
-- and subquery foo is also replaced since it contains
|
||||||
|
-- DISTINCT on a non-partition key
|
||||||
|
SELECT * FROM
|
||||||
|
(
|
||||||
|
WITH cte AS (
|
||||||
|
WITH local_cte AS (
|
||||||
|
SELECT * FROM users_table_local
|
||||||
|
),
|
||||||
|
dist_cte AS (
|
||||||
|
SELECT user_id FROM events_table
|
||||||
|
)
|
||||||
|
SELECT dist_cte.user_id FROM local_cte join dist_cte on dist_cte.user_id=local_cte.user_id
|
||||||
|
)
|
||||||
|
SELECT DISTINCT cte.user_id
|
||||||
|
FROM users_table, cte
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = cte.user_id AND
|
||||||
|
users_table.user_id IN
|
||||||
|
(WITH cte_in_where AS (SELECT DISTINCT value_2 FROM users_table WHERE value_1 >= 1 AND value_1 <= 20 ORDER BY 1 LIMIT 5) SELECT * FROM cte_in_where)
|
||||||
|
ORDER BY 1 DESC
|
||||||
|
) as foo,
|
||||||
|
events_table
|
||||||
|
WHERE
|
||||||
|
foo.user_id = events_table.value_2
|
||||||
|
ORDER BY 3 DESC, 2 DESC, 1 DESC
|
||||||
|
LIMIT 5;
|
||||||
|
DEBUG: generating subplan 25_1 for CTE cte: WITH local_cte AS (SELECT users_table_local.user_id, users_table_local."time", users_table_local.value_1, users_table_local.value_2, users_table_local.value_3, users_table_local.value_4 FROM subquery_and_ctes.users_table_local), dist_cte AS (SELECT events_table.user_id FROM public.events_table) SELECT dist_cte.user_id FROM (local_cte JOIN dist_cte ON ((dist_cte.user_id = local_cte.user_id)))
|
||||||
|
DEBUG: generating subplan 26_1 for CTE local_cte: SELECT user_id, "time", value_1, value_2, value_3, value_4 FROM subquery_and_ctes.users_table_local
|
||||||
|
DEBUG: generating subplan 26_2 for CTE dist_cte: SELECT user_id FROM public.events_table
|
||||||
|
DEBUG: generating subplan 25_2 for CTE cte_in_where: SELECT DISTINCT value_2 FROM public.users_table WHERE ((value_1 >= 1) AND (value_1 <= 20)) ORDER BY value_2 LIMIT 5
|
||||||
|
DEBUG: push down of limit count: 5
|
||||||
|
DEBUG: generating subplan 25_3 for subquery SELECT DISTINCT cte.user_id FROM public.users_table, (SELECT intermediate_result.user_id FROM read_intermediate_result('25_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) cte WHERE ((users_table.user_id = cte.user_id) AND (users_table.user_id IN (SELECT cte_in_where.value_2 FROM (SELECT intermediate_result.value_2 FROM read_intermediate_result('25_2'::text, 'binary'::citus_copy_format) intermediate_result(value_2 integer)) cte_in_where))) ORDER BY cte.user_id DESC
|
||||||
|
DEBUG: push down of limit count: 5
|
||||||
|
user_id | user_id | time | event_type | value_2 | value_3 | value_4
|
||||||
|
---------+---------+---------------------------------+------------+---------+---------+---------
|
||||||
|
4 | 1 | Thu Nov 23 21:54:46.924477 2017 | 6 | 4 | 5 |
|
||||||
|
2 | 4 | Thu Nov 23 18:10:21.338399 2017 | 1 | 2 | 4 |
|
||||||
|
4 | 3 | Thu Nov 23 18:08:26.550729 2017 | 2 | 4 | 3 |
|
||||||
|
2 | 3 | Thu Nov 23 16:44:41.903713 2017 | 4 | 2 | 2 |
|
||||||
|
1 | 3 | Thu Nov 23 16:31:56.219594 2017 | 5 | 1 | 2 |
|
||||||
|
(5 rows)
|
||||||
|
|
||||||
|
-- now recursively plan subqueries inside the CTEs that contains LIMIT and OFFSET
|
||||||
|
WITH cte AS (
|
||||||
|
WITH local_cte AS (
|
||||||
|
SELECT * FROM users_table_local
|
||||||
|
),
|
||||||
|
dist_cte AS (
|
||||||
|
SELECT
|
||||||
|
user_id
|
||||||
|
FROM
|
||||||
|
events_table,
|
||||||
|
(SELECT DISTINCT value_2 FROM users_table OFFSET 0) as foo
|
||||||
|
WHERE
|
||||||
|
events_table.user_id = foo.value_2 AND
|
||||||
|
events_table.user_id IN (SELECT DISTINCT value_1 FROM users_table ORDER BY 1 LIMIT 3)
|
||||||
|
)
|
||||||
|
SELECT dist_cte.user_id FROM local_cte join dist_cte on dist_cte.user_id=local_cte.user_id
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
count(*)
|
||||||
|
FROM
|
||||||
|
cte,
|
||||||
|
(SELECT
|
||||||
|
DISTINCT users_table.user_id
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
ORDER BY 1 DESC LIMIT 5
|
||||||
|
) as foo
|
||||||
|
WHERE foo.user_id = cte.user_id;
|
||||||
|
DEBUG: generating subplan 30_1 for CTE cte: WITH local_cte AS (SELECT users_table_local.user_id, users_table_local."time", users_table_local.value_1, users_table_local.value_2, users_table_local.value_3, users_table_local.value_4 FROM subquery_and_ctes.users_table_local), dist_cte AS (SELECT events_table.user_id FROM public.events_table, (SELECT DISTINCT users_table.value_2 FROM public.users_table OFFSET 0) foo WHERE ((events_table.user_id = foo.value_2) AND (events_table.user_id IN (SELECT DISTINCT users_table.value_1 FROM public.users_table ORDER BY users_table.value_1 LIMIT 3)))) SELECT dist_cte.user_id FROM (local_cte JOIN dist_cte ON ((dist_cte.user_id = local_cte.user_id)))
|
||||||
|
DEBUG: generating subplan 31_1 for CTE local_cte: SELECT user_id, "time", value_1, value_2, value_3, value_4 FROM subquery_and_ctes.users_table_local
|
||||||
|
DEBUG: generating subplan 31_2 for CTE dist_cte: SELECT events_table.user_id FROM public.events_table, (SELECT DISTINCT users_table.value_2 FROM public.users_table OFFSET 0) foo WHERE ((events_table.user_id = foo.value_2) AND (events_table.user_id IN (SELECT DISTINCT users_table.value_1 FROM public.users_table ORDER BY users_table.value_1 LIMIT 3)))
|
||||||
|
DEBUG: push down of limit count: 3
|
||||||
|
DEBUG: generating subplan 32_1 for subquery SELECT DISTINCT value_1 FROM public.users_table ORDER BY value_1 LIMIT 3
|
||||||
|
DEBUG: generating subplan 32_2 for subquery SELECT DISTINCT value_2 FROM public.users_table OFFSET 0
|
||||||
|
DEBUG: push down of limit count: 5
|
||||||
|
DEBUG: generating subplan 30_2 for subquery SELECT DISTINCT users_table.user_id FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.user_id) AND (events_table.event_type = ANY (ARRAY[1, 2, 3, 4]))) ORDER BY users_table.user_id DESC LIMIT 5
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
432
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- the same query, but this time the CTEs also live inside a subquery
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
WITH cte AS (
|
||||||
|
WITH local_cte AS (
|
||||||
|
SELECT * FROM users_table_local
|
||||||
|
),
|
||||||
|
dist_cte AS (
|
||||||
|
SELECT
|
||||||
|
user_id
|
||||||
|
FROM
|
||||||
|
events_table,
|
||||||
|
(SELECT DISTINCT value_2 FROM users_table OFFSET 0) as foo
|
||||||
|
WHERE
|
||||||
|
events_table.user_id = foo.value_2 AND
|
||||||
|
events_table.user_id IN (SELECT DISTINCT value_1 FROM users_table ORDER BY 1 LIMIT 3)
|
||||||
|
)
|
||||||
|
SELECT dist_cte.user_id FROM local_cte join dist_cte on dist_cte.user_id=local_cte.user_id
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
count(*) as cnt
|
||||||
|
FROM
|
||||||
|
cte,
|
||||||
|
(SELECT
|
||||||
|
DISTINCT users_table.user_id
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
ORDER BY 1 DESC LIMIT 5
|
||||||
|
) as foo
|
||||||
|
WHERE foo.user_id = cte.user_id
|
||||||
|
) as foo, users_table WHERE foo.cnt > users_table.value_2
|
||||||
|
ORDER BY 3 DESC, 1 DESC, 2 DESC, 4 DESC
|
||||||
|
LIMIT 5;
|
||||||
|
DEBUG: generating subplan 36_1 for CTE cte: WITH local_cte AS (SELECT users_table_local.user_id, users_table_local."time", users_table_local.value_1, users_table_local.value_2, users_table_local.value_3, users_table_local.value_4 FROM subquery_and_ctes.users_table_local), dist_cte AS (SELECT events_table.user_id FROM public.events_table, (SELECT DISTINCT users_table.value_2 FROM public.users_table OFFSET 0) foo WHERE ((events_table.user_id = foo.value_2) AND (events_table.user_id IN (SELECT DISTINCT users_table.value_1 FROM public.users_table ORDER BY users_table.value_1 LIMIT 3)))) SELECT dist_cte.user_id FROM (local_cte JOIN dist_cte ON ((dist_cte.user_id = local_cte.user_id)))
|
||||||
|
DEBUG: generating subplan 37_1 for CTE local_cte: SELECT user_id, "time", value_1, value_2, value_3, value_4 FROM subquery_and_ctes.users_table_local
|
||||||
|
DEBUG: generating subplan 37_2 for CTE dist_cte: SELECT events_table.user_id FROM public.events_table, (SELECT DISTINCT users_table.value_2 FROM public.users_table OFFSET 0) foo WHERE ((events_table.user_id = foo.value_2) AND (events_table.user_id IN (SELECT DISTINCT users_table.value_1 FROM public.users_table ORDER BY users_table.value_1 LIMIT 3)))
|
||||||
|
DEBUG: push down of limit count: 3
|
||||||
|
DEBUG: generating subplan 38_1 for subquery SELECT DISTINCT value_1 FROM public.users_table ORDER BY value_1 LIMIT 3
|
||||||
|
DEBUG: generating subplan 38_2 for subquery SELECT DISTINCT value_2 FROM public.users_table OFFSET 0
|
||||||
|
DEBUG: push down of limit count: 5
|
||||||
|
DEBUG: generating subplan 36_2 for subquery SELECT DISTINCT users_table.user_id FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.user_id) AND (events_table.event_type = ANY (ARRAY[1, 2, 3, 4]))) ORDER BY users_table.user_id DESC LIMIT 5
|
||||||
|
DEBUG: generating subplan 36_3 for subquery SELECT count(*) AS cnt FROM (SELECT intermediate_result.user_id FROM read_intermediate_result('36_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) cte, (SELECT intermediate_result.user_id FROM read_intermediate_result('36_2'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) foo WHERE (foo.user_id = cte.user_id)
|
||||||
|
DEBUG: push down of limit count: 5
|
||||||
|
cnt | user_id | time | value_1 | value_2 | value_3 | value_4
|
||||||
|
-----+---------+---------------------------------+---------+---------+---------+---------
|
||||||
|
432 | 1 | Thu Nov 23 17:30:34.635085 2017 | 3 | 4 | 4 |
|
||||||
|
432 | 1 | Thu Nov 23 17:23:03.441394 2017 | 5 | 4 | 3 |
|
||||||
|
432 | 3 | Thu Nov 23 17:18:51.048758 2017 | 1 | 5 | 5 |
|
||||||
|
432 | 3 | Thu Nov 23 17:10:35.959913 2017 | 4 | 3 | 1 |
|
||||||
|
432 | 5 | Thu Nov 23 16:48:32.08896 2017 | 5 | 2 | 1 |
|
||||||
|
(5 rows)
|
||||||
|
|
||||||
|
-- recursive CTES are not supported inside subqueries as well
|
||||||
|
SELECT
|
||||||
|
bar.user_id
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
WITH RECURSIVE cte AS (
|
||||||
|
SELECT
|
||||||
|
DISTINCT users_table.user_id
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
) SELECT * FROM cte ORDER BY 1 DESC
|
||||||
|
) as foo,
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
DISTINCT users_table.user_id
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
|
||||||
|
) as bar
|
||||||
|
WHERE foo.user_id = bar.user_id;
|
||||||
|
ERROR: recursive CTEs are not supported in distributed queries
|
||||||
|
SET client_min_messages TO DEFAULT;
|
||||||
|
DROP SCHEMA subquery_and_ctes CASCADE;
|
||||||
|
NOTICE: drop cascades to table users_table_local
|
||||||
|
SET search_path TO public;
|
|
@ -0,0 +1,347 @@
|
||||||
|
-- ===================================================================
|
||||||
|
-- test recursive planning functionality
|
||||||
|
-- ===================================================================
|
||||||
|
SET client_min_messages TO DEBUG1;
|
||||||
|
-- subqueries in FROM clause with LIMIT should be recursively planned
|
||||||
|
SELECT
|
||||||
|
user_id
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
DISTINCT users_table.user_id
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
ORDER BY 1 DESC LIMIT 5
|
||||||
|
) as foo
|
||||||
|
ORDER BY 1 DESC;
|
||||||
|
DEBUG: push down of limit count: 5
|
||||||
|
DEBUG: generating subplan 1_1 for subquery SELECT DISTINCT users_table.user_id FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.user_id) AND (events_table.event_type = ANY (ARRAY[1, 2, 3, 4]))) ORDER BY users_table.user_id DESC LIMIT 5
|
||||||
|
user_id
|
||||||
|
---------
|
||||||
|
6
|
||||||
|
5
|
||||||
|
4
|
||||||
|
3
|
||||||
|
2
|
||||||
|
(5 rows)
|
||||||
|
|
||||||
|
-- subqueries in FROM clause with DISTINCT on non-partition key
|
||||||
|
-- should be recursively planned
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
DISTINCT users_table.value_1
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
ORDER BY 1
|
||||||
|
) as foo
|
||||||
|
ORDER BY 1 DESC;
|
||||||
|
DEBUG: generating subplan 3_1 for subquery SELECT DISTINCT users_table.value_1 FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.user_id) AND (events_table.event_type = ANY (ARRAY[1, 2, 3, 4]))) ORDER BY users_table.value_1
|
||||||
|
value_1
|
||||||
|
---------
|
||||||
|
5
|
||||||
|
4
|
||||||
|
3
|
||||||
|
2
|
||||||
|
1
|
||||||
|
0
|
||||||
|
(6 rows)
|
||||||
|
|
||||||
|
-- subqueries in FROM clause with GROUP BY on non-partition key
|
||||||
|
-- should be recursively planned
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
users_table.value_2, avg(value_1)
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
GROUP BY users_table.value_2
|
||||||
|
ORDER BY 1 DESC
|
||||||
|
) as foo
|
||||||
|
ORDER BY 2 DESC, 1;
|
||||||
|
DEBUG: generating subplan 5_1 for subquery SELECT users_table.value_2, avg(users_table.value_1) AS avg FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.user_id) AND (events_table.event_type = ANY (ARRAY[1, 2, 3, 4]))) GROUP BY users_table.value_2 ORDER BY users_table.value_2 DESC
|
||||||
|
value_2 | avg
|
||||||
|
---------+--------------------
|
||||||
|
4 | 2.8453608247422680
|
||||||
|
2 | 2.6833855799373041
|
||||||
|
5 | 2.6238938053097345
|
||||||
|
1 | 2.3569131832797428
|
||||||
|
3 | 2.3424124513618677
|
||||||
|
0 | 2.0940170940170940
|
||||||
|
(6 rows)
|
||||||
|
|
||||||
|
-- multiple subqueries in FROM clause should be replaced
|
||||||
|
-- and the final query is router query
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
users_table.value_2
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
GROUP BY users_table.value_2
|
||||||
|
ORDER BY 1 DESC
|
||||||
|
) as foo,
|
||||||
|
(SELECT
|
||||||
|
users_table.value_3
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (5,6,7,8)
|
||||||
|
GROUP BY users_table.value_3
|
||||||
|
ORDER BY 1 DESC
|
||||||
|
) as bar
|
||||||
|
WHERE foo.value_2 = bar.value_3
|
||||||
|
ORDER BY 2 DESC, 1;
|
||||||
|
DEBUG: generating subplan 7_1 for subquery SELECT users_table.value_2 FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.user_id) AND (events_table.event_type = ANY (ARRAY[1, 2, 3, 4]))) GROUP BY users_table.value_2 ORDER BY users_table.value_2 DESC
|
||||||
|
DEBUG: generating subplan 7_2 for subquery SELECT users_table.value_3 FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.user_id) AND (events_table.event_type = ANY (ARRAY[5, 6, 7, 8]))) GROUP BY users_table.value_3 ORDER BY users_table.value_3 DESC
|
||||||
|
value_2 | value_3
|
||||||
|
---------+---------
|
||||||
|
5 | 5
|
||||||
|
4 | 4
|
||||||
|
3 | 3
|
||||||
|
2 | 2
|
||||||
|
1 | 1
|
||||||
|
0 | 0
|
||||||
|
(6 rows)
|
||||||
|
|
||||||
|
-- same query with alias in the subquery
|
||||||
|
SELECT
|
||||||
|
DISTINCT ON (citus) citus, postgres, citus + 1 as c1, postgres-1 as p1
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
users_table.value_2
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
GROUP BY users_table.value_2
|
||||||
|
ORDER BY 1 DESC
|
||||||
|
) as foo(postgres),
|
||||||
|
(SELECT
|
||||||
|
users_table.user_id
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (5,6,7,8)
|
||||||
|
ORDER BY 1 DESC
|
||||||
|
) as bar (citus)
|
||||||
|
WHERE foo.postgres = bar.citus
|
||||||
|
ORDER BY 1 DESC, 2 DESC
|
||||||
|
LIMIT 3;
|
||||||
|
DEBUG: generating subplan 10_1 for subquery SELECT users_table.value_2 FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.user_id) AND (events_table.event_type = ANY (ARRAY[1, 2, 3, 4]))) GROUP BY users_table.value_2 ORDER BY users_table.value_2 DESC
|
||||||
|
DEBUG: push down of limit count: 3
|
||||||
|
citus | postgres | c1 | p1
|
||||||
|
-------+----------+----+----
|
||||||
|
5 | 5 | 6 | 4
|
||||||
|
4 | 4 | 5 | 3
|
||||||
|
3 | 3 | 4 | 2
|
||||||
|
(3 rows)
|
||||||
|
|
||||||
|
-- foo is replaced
|
||||||
|
-- and the final query is real-time
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
users_table.value_2
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
GROUP BY users_table.value_2
|
||||||
|
ORDER BY 1 DESC
|
||||||
|
) as foo,
|
||||||
|
(SELECT
|
||||||
|
users_table.user_id
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (5,6,7,8)
|
||||||
|
ORDER BY 1 DESC
|
||||||
|
) as bar
|
||||||
|
WHERE foo.value_2 = bar.user_id
|
||||||
|
ORDER BY 2 DESC, 1 DESC
|
||||||
|
LIMIT 3;
|
||||||
|
DEBUG: generating subplan 12_1 for subquery SELECT users_table.value_2 FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.user_id) AND (events_table.event_type = ANY (ARRAY[1, 2, 3, 4]))) GROUP BY users_table.value_2 ORDER BY users_table.value_2 DESC
|
||||||
|
DEBUG: push down of limit count: 3
|
||||||
|
value_2 | user_id
|
||||||
|
---------+---------
|
||||||
|
5 | 5
|
||||||
|
5 | 5
|
||||||
|
5 | 5
|
||||||
|
(3 rows)
|
||||||
|
|
||||||
|
-- subqueries in WHERE should be replaced
|
||||||
|
SELECT DISTINCT user_id
|
||||||
|
FROM users_table
|
||||||
|
WHERE
|
||||||
|
user_id IN (SELECT DISTINCT value_2 FROM users_table WHERE value_1 >= 1 AND value_1 <= 20 ORDER BY 1 LIMIT 5)
|
||||||
|
ORDER BY 1 DESC;
|
||||||
|
DEBUG: push down of limit count: 5
|
||||||
|
DEBUG: generating subplan 14_1 for subquery SELECT DISTINCT value_2 FROM public.users_table WHERE ((value_1 >= 1) AND (value_1 <= 20)) ORDER BY value_2 LIMIT 5
|
||||||
|
user_id
|
||||||
|
---------
|
||||||
|
4
|
||||||
|
3
|
||||||
|
2
|
||||||
|
1
|
||||||
|
(4 rows)
|
||||||
|
|
||||||
|
-- subquery in FROM -> FROM -> FROM should be replaced due to OFFSET
|
||||||
|
SELECT
|
||||||
|
DISTINCT user_id
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT users_table.user_id FROM users_table,
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
event_type, user_id
|
||||||
|
FROM
|
||||||
|
(SELECT event_type, users_table.user_id FROM users_table,
|
||||||
|
(SELECT user_id, event_type FROM events_table WHERE value_2 < 3 OFFSET 3) as foo
|
||||||
|
WHERE foo.user_id = users_table.user_id
|
||||||
|
) bar
|
||||||
|
) as baz
|
||||||
|
WHERE baz.user_id = users_table.user_id
|
||||||
|
) as sub1
|
||||||
|
ORDER BY 1 DESC
|
||||||
|
LIMIT 3;
|
||||||
|
DEBUG: generating subplan 16_1 for subquery SELECT user_id, event_type FROM public.events_table WHERE (value_2 < 3) OFFSET 3
|
||||||
|
DEBUG: push down of limit count: 3
|
||||||
|
user_id
|
||||||
|
---------
|
||||||
|
6
|
||||||
|
5
|
||||||
|
4
|
||||||
|
(3 rows)
|
||||||
|
|
||||||
|
-- subquery in FROM -> FROM -> WHERE should be replaced due to LIMIT
|
||||||
|
SELECT user_id, array_length(events_table, 1)
|
||||||
|
FROM (
|
||||||
|
SELECT user_id, array_agg(event ORDER BY time) AS events_table
|
||||||
|
FROM (
|
||||||
|
SELECT
|
||||||
|
u.user_id, e.event_type::text AS event, e.time
|
||||||
|
FROM
|
||||||
|
users_table AS u,
|
||||||
|
events_table AS e
|
||||||
|
WHERE u.user_id = e.user_id AND
|
||||||
|
u.user_id IN
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
user_id
|
||||||
|
FROM
|
||||||
|
users_table
|
||||||
|
WHERE value_2 >= 5
|
||||||
|
AND EXISTS (SELECT user_id FROM events_table WHERE event_type > 1 AND event_type <= 3 AND value_3 > 1 AND user_id = users_table.user_id)
|
||||||
|
AND NOT EXISTS (SELECT user_id FROM events_table WHERE event_type > 3 AND event_type <= 4 AND value_3 > 1 AND user_id = users_table.user_id)
|
||||||
|
LIMIT 5
|
||||||
|
)
|
||||||
|
) t
|
||||||
|
GROUP BY user_id
|
||||||
|
) q
|
||||||
|
ORDER BY 2 DESC, 1;
|
||||||
|
DEBUG: push down of limit count: 5
|
||||||
|
DEBUG: generating subplan 18_1 for subquery SELECT user_id FROM public.users_table WHERE ((value_2 >= 5) AND (EXISTS (SELECT events_table.user_id FROM public.events_table WHERE ((events_table.event_type > 1) AND (events_table.event_type <= 3) AND (events_table.value_3 > (1)::double precision) AND (events_table.user_id = users_table.user_id)))) AND (NOT (EXISTS (SELECT events_table.user_id FROM public.events_table WHERE ((events_table.event_type > 3) AND (events_table.event_type <= 4) AND (events_table.value_3 > (1)::double precision) AND (events_table.user_id = users_table.user_id)))))) LIMIT 5
|
||||||
|
user_id | array_length
|
||||||
|
---------+--------------
|
||||||
|
5 | 364
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- subquery (i.e., subquery_2) in WHERE->FROM should be replaced due to LIMIT
|
||||||
|
SELECT
|
||||||
|
user_id
|
||||||
|
FROM
|
||||||
|
users_table
|
||||||
|
WHERE
|
||||||
|
user_id IN
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
user_id
|
||||||
|
FROM (
|
||||||
|
SELECT
|
||||||
|
subquery_1.user_id, count_pay
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
(SELECT
|
||||||
|
users_table.user_id,
|
||||||
|
'action=>1' AS event,
|
||||||
|
events_table.time
|
||||||
|
FROM
|
||||||
|
users_table,
|
||||||
|
events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
users_table.user_id >= 1 AND
|
||||||
|
users_table.user_id <= 3 AND
|
||||||
|
events_table.event_type > 1 AND events_table.event_type < 3
|
||||||
|
)
|
||||||
|
UNION
|
||||||
|
(SELECT
|
||||||
|
users_table.user_id,
|
||||||
|
'action=>2' AS event,
|
||||||
|
events_table.time
|
||||||
|
FROM
|
||||||
|
users_table,
|
||||||
|
events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
users_table.user_id >= 1 AND
|
||||||
|
users_table.user_id <= 3 AND
|
||||||
|
events_table.event_type > 2 AND events_table.event_type < 4
|
||||||
|
)
|
||||||
|
) AS subquery_1
|
||||||
|
LEFT JOIN
|
||||||
|
(SELECT
|
||||||
|
user_id,
|
||||||
|
COUNT(*) AS count_pay
|
||||||
|
FROM
|
||||||
|
users_table
|
||||||
|
WHERE
|
||||||
|
user_id >= 1 AND
|
||||||
|
user_id <= 3 AND
|
||||||
|
users_table.value_1 > 3 AND users_table.value_1 < 5
|
||||||
|
GROUP BY
|
||||||
|
user_id
|
||||||
|
HAVING
|
||||||
|
COUNT(*) > 1
|
||||||
|
LIMIT 10
|
||||||
|
) AS subquery_2
|
||||||
|
ON
|
||||||
|
subquery_1.user_id = subquery_2.user_id
|
||||||
|
GROUP BY
|
||||||
|
subquery_1.user_id,
|
||||||
|
count_pay) AS subquery_top
|
||||||
|
GROUP BY
|
||||||
|
count_pay, user_id
|
||||||
|
)
|
||||||
|
GROUP BY user_id
|
||||||
|
HAVING count(*) > 1 AND sum(value_2) > 29
|
||||||
|
ORDER BY 1;
|
||||||
|
DEBUG: push down of limit count: 10
|
||||||
|
DEBUG: generating subplan 20_1 for subquery SELECT user_id, count(*) AS count_pay FROM public.users_table WHERE ((user_id >= 1) AND (user_id <= 3) AND (value_1 > 3) AND (value_1 < 5)) GROUP BY user_id HAVING (count(*) > 1) LIMIT 10
|
||||||
|
user_id
|
||||||
|
---------
|
||||||
|
2
|
||||||
|
3
|
||||||
|
(2 rows)
|
||||||
|
|
|
@ -0,0 +1,143 @@
|
||||||
|
-- ===================================================================
|
||||||
|
-- test recursive planning functionality with different executors
|
||||||
|
-- ===================================================================
|
||||||
|
CREATE SCHEMA subquery_executor;
|
||||||
|
SET search_path TO subquery_executor, public;
|
||||||
|
CREATE TABLE users_table_local AS SELECT * FROM users_table;
|
||||||
|
SET client_min_messages TO DEBUG1;
|
||||||
|
-- subquery with router planner
|
||||||
|
SELECT
|
||||||
|
count(*)
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT value_2 FROM users_table WHERE user_id = 15 OFFSET 0
|
||||||
|
) as foo,
|
||||||
|
(
|
||||||
|
SELECT user_id FROM users_table
|
||||||
|
) as bar
|
||||||
|
WHERE foo.value_2 = bar.user_id;
|
||||||
|
DEBUG: generating subplan 2_1 for subquery SELECT value_2 FROM public.users_table WHERE (user_id = 15) OFFSET 0
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
0
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- subquery with router but not logical plannable
|
||||||
|
-- should fail
|
||||||
|
SELECT
|
||||||
|
count(*)
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT user_id, sum(value_2) over (partition by user_id) AS counter FROM users_table WHERE user_id = 15
|
||||||
|
) as foo,
|
||||||
|
(
|
||||||
|
SELECT user_id FROM users_table
|
||||||
|
) as bar
|
||||||
|
WHERE foo.counter = bar.user_id;
|
||||||
|
ERROR: cannot pushdown the subquery since all relations are not joined using distribution keys
|
||||||
|
DETAIL: Each relation should be joined with at least one another relation using distribution keys and equality operator.
|
||||||
|
-- subquery with real-time query
|
||||||
|
SELECT
|
||||||
|
count(*)
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT value_2 FROM users_table WHERE user_id != 15 OFFSET 0
|
||||||
|
) as foo,
|
||||||
|
(
|
||||||
|
SELECT user_id FROM users_table
|
||||||
|
) as bar
|
||||||
|
WHERE foo.value_2 = bar.user_id;
|
||||||
|
DEBUG: generating subplan 5_1 for subquery SELECT value_2 FROM public.users_table WHERE (user_id <> 15) OFFSET 0
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
1612
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- subquery with repartition query
|
||||||
|
SET citus.enable_repartition_joins to ON;
|
||||||
|
SELECT
|
||||||
|
count(*)
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT DISTINCT users_table.value_2 FROM users_table, events_table WHERE users_table.user_id = events_table.value_2 AND users_table.user_id < 2
|
||||||
|
) as foo,
|
||||||
|
(
|
||||||
|
SELECT user_id FROM users_table
|
||||||
|
) as bar
|
||||||
|
WHERE foo.value_2 = bar.user_id;
|
||||||
|
DEBUG: cannot use real time executor with repartition jobs
|
||||||
|
HINT: Since you enabled citus.enable_repartition_joins Citus chose to use task-tracker.
|
||||||
|
DEBUG: generating subplan 7_1 for subquery SELECT DISTINCT users_table.value_2 FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.value_2) AND (users_table.user_id < 2))
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
58
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- mixed of all executors (including local execution)
|
||||||
|
SELECT
|
||||||
|
count(*)
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT value_2 FROM users_table WHERE user_id = 15 OFFSET 0
|
||||||
|
) as foo,
|
||||||
|
(
|
||||||
|
SELECT user_id FROM users_table OFFSET 0
|
||||||
|
) as bar,
|
||||||
|
(
|
||||||
|
SELECT DISTINCT users_table.value_2 FROM users_table, events_table WHERE users_table.user_id = events_table.value_2 AND users_table.user_id < 2
|
||||||
|
) baz,
|
||||||
|
(
|
||||||
|
SELECT user_id FROM users_table_local WHERE user_id = 2
|
||||||
|
) baw
|
||||||
|
WHERE foo.value_2 = bar.user_id AND baz.value_2 = bar.user_id AND bar.user_id = baw.user_id;
|
||||||
|
DEBUG: generating subplan 9_1 for subquery SELECT value_2 FROM public.users_table WHERE (user_id = 15) OFFSET 0
|
||||||
|
DEBUG: generating subplan 9_2 for subquery SELECT user_id FROM public.users_table OFFSET 0
|
||||||
|
DEBUG: cannot use real time executor with repartition jobs
|
||||||
|
HINT: Since you enabled citus.enable_repartition_joins Citus chose to use task-tracker.
|
||||||
|
DEBUG: generating subplan 9_3 for subquery SELECT DISTINCT users_table.value_2 FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.value_2) AND (users_table.user_id < 2))
|
||||||
|
DEBUG: generating subplan 9_4 for subquery SELECT user_id FROM subquery_executor.users_table_local WHERE (user_id = 2)
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
0
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SET citus.enable_repartition_joins to OFF;
|
||||||
|
-- final query is router
|
||||||
|
SELECT
|
||||||
|
count(*)
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT value_2 FROM users_table WHERE user_id = 1 OFFSET 0
|
||||||
|
) as foo,
|
||||||
|
(
|
||||||
|
SELECT user_id FROM users_table WHERE user_id = 2 OFFSET 0
|
||||||
|
) as bar
|
||||||
|
WHERE foo.value_2 = bar.user_id;
|
||||||
|
DEBUG: generating subplan 13_1 for subquery SELECT value_2 FROM public.users_table WHERE (user_id = 1) OFFSET 0
|
||||||
|
DEBUG: generating subplan 13_2 for subquery SELECT user_id FROM public.users_table WHERE (user_id = 2) OFFSET 0
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
18
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- final query is real-time
|
||||||
|
SELECT
|
||||||
|
count(*)
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT value_2 FROM users_table WHERE user_id = 1 OFFSET 0
|
||||||
|
) as foo,
|
||||||
|
(
|
||||||
|
SELECT user_id FROM users_table WHERE user_id != 2
|
||||||
|
) as bar
|
||||||
|
WHERE foo.value_2 = bar.user_id;
|
||||||
|
DEBUG: generating subplan 16_1 for subquery SELECT value_2 FROM public.users_table WHERE (user_id = 1) OFFSET 0
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
103
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SET client_min_messages TO DEFAULT;
|
||||||
|
DROP SCHEMA subquery_executor CASCADE;
|
||||||
|
NOTICE: drop cascades to table users_table_local
|
||||||
|
SET search_path TO public;
|
|
@ -0,0 +1,243 @@
|
||||||
|
-- ===================================================================
|
||||||
|
-- test recursive planning functionality on local tables
|
||||||
|
-- ===================================================================
|
||||||
|
CREATE SCHEMA subquery_local_tables;
|
||||||
|
SET search_path TO subquery_local_tables, public;
|
||||||
|
CREATE TABLE users_table_local AS SELECT * FROM users_table;
|
||||||
|
CREATE TABLE events_table_local AS SELECT * FROM events_table;
|
||||||
|
SET client_min_messages TO DEBUG1;
|
||||||
|
-- foo is only on the local tables, thus can be replaced
|
||||||
|
-- bar is on the distributed tables with LIMIT, should be replaced
|
||||||
|
SELECT
|
||||||
|
foo.user_id
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
DISTINCT users_table_local.user_id
|
||||||
|
FROM
|
||||||
|
users_table_local, events_table_local
|
||||||
|
WHERE
|
||||||
|
users_table_local.user_id = events_table_local.user_id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
ORDER BY 1 DESC LIMIT 5
|
||||||
|
) as foo,
|
||||||
|
(SELECT
|
||||||
|
DISTINCT users_table.user_id
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (5,6,7,8)
|
||||||
|
ORDER BY 1 DESC LIMIT 5
|
||||||
|
) as bar
|
||||||
|
WHERE bar.user_id = foo.user_id
|
||||||
|
ORDER BY 1 DESC;
|
||||||
|
DEBUG: generating subplan 3_1 for subquery SELECT DISTINCT users_table_local.user_id FROM subquery_local_tables.users_table_local, subquery_local_tables.events_table_local WHERE ((users_table_local.user_id = events_table_local.user_id) AND (events_table_local.event_type = ANY (ARRAY[1, 2, 3, 4]))) ORDER BY users_table_local.user_id DESC LIMIT 5
|
||||||
|
DEBUG: push down of limit count: 5
|
||||||
|
DEBUG: generating subplan 3_2 for subquery SELECT DISTINCT users_table.user_id FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.user_id) AND (events_table.event_type = ANY (ARRAY[5, 6, 7, 8]))) ORDER BY users_table.user_id DESC LIMIT 5
|
||||||
|
user_id
|
||||||
|
---------
|
||||||
|
6
|
||||||
|
5
|
||||||
|
4
|
||||||
|
3
|
||||||
|
2
|
||||||
|
(5 rows)
|
||||||
|
|
||||||
|
-- foo is only on the local tables, thus can be replaced
|
||||||
|
SELECT
|
||||||
|
foo.user_id
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
DISTINCT users_table_local.user_id
|
||||||
|
FROM
|
||||||
|
users_table_local, events_table_local
|
||||||
|
WHERE
|
||||||
|
users_table_local.user_id = events_table_local.user_id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
ORDER BY 1 DESC LIMIT 5
|
||||||
|
) as foo,
|
||||||
|
(SELECT
|
||||||
|
DISTINCT users_table.user_id
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (5,6,7,8)
|
||||||
|
) as bar
|
||||||
|
WHERE bar.user_id = foo.user_id
|
||||||
|
ORDER BY 1 DESC;
|
||||||
|
DEBUG: generating subplan 5_1 for subquery SELECT DISTINCT users_table_local.user_id FROM subquery_local_tables.users_table_local, subquery_local_tables.events_table_local WHERE ((users_table_local.user_id = events_table_local.user_id) AND (events_table_local.event_type = ANY (ARRAY[1, 2, 3, 4]))) ORDER BY users_table_local.user_id DESC LIMIT 5
|
||||||
|
user_id
|
||||||
|
---------
|
||||||
|
6
|
||||||
|
5
|
||||||
|
4
|
||||||
|
3
|
||||||
|
2
|
||||||
|
(5 rows)
|
||||||
|
|
||||||
|
-- subqueries in WHERE could be replaced even if they are on the local tables
|
||||||
|
SELECT DISTINCT user_id
|
||||||
|
FROM users_table
|
||||||
|
WHERE
|
||||||
|
user_id IN (SELECT DISTINCT value_2 FROM users_table_local WHERE value_1 = 1)
|
||||||
|
ORDER BY 1 LIMIT 5;
|
||||||
|
DEBUG: generating subplan 6_1 for subquery SELECT DISTINCT value_2 FROM subquery_local_tables.users_table_local WHERE (value_1 = 1)
|
||||||
|
DEBUG: push down of limit count: 5
|
||||||
|
user_id
|
||||||
|
---------
|
||||||
|
1
|
||||||
|
2
|
||||||
|
3
|
||||||
|
4
|
||||||
|
5
|
||||||
|
(5 rows)
|
||||||
|
|
||||||
|
-- subquery in FROM -> FROM -> FROM should be replaced if
|
||||||
|
-- it contains onle local tables
|
||||||
|
SELECT
|
||||||
|
DISTINCT user_id
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT users_table.user_id FROM users_table,
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
event_type, user_id
|
||||||
|
FROM
|
||||||
|
(SELECT event_type, users_table.user_id FROM users_table,
|
||||||
|
(SELECT user_id, event_type FROM events_table_local WHERE value_2 < 3 OFFSET 3) as foo
|
||||||
|
WHERE foo.user_id = users_table.user_id
|
||||||
|
) bar
|
||||||
|
) as baz
|
||||||
|
WHERE baz.user_id = users_table.user_id
|
||||||
|
) as sub1
|
||||||
|
ORDER BY 1 DESC
|
||||||
|
LIMIT 3;
|
||||||
|
DEBUG: generating subplan 7_1 for subquery SELECT user_id, event_type FROM subquery_local_tables.events_table_local WHERE (value_2 < 3) OFFSET 3
|
||||||
|
DEBUG: push down of limit count: 3
|
||||||
|
user_id
|
||||||
|
---------
|
||||||
|
6
|
||||||
|
5
|
||||||
|
4
|
||||||
|
(3 rows)
|
||||||
|
|
||||||
|
-- subquery in FROM -> FROM -> WHERE -> WHERE should be replaced if
|
||||||
|
-- it contains onle local tables
|
||||||
|
-- Later the upper level query is also recursively planned due to LIMIT
|
||||||
|
SELECT user_id, array_length(events_table, 1)
|
||||||
|
FROM (
|
||||||
|
SELECT user_id, array_agg(event ORDER BY time) AS events_table
|
||||||
|
FROM (
|
||||||
|
SELECT
|
||||||
|
u.user_id, e.event_type::text AS event, e.time
|
||||||
|
FROM
|
||||||
|
users_table AS u,
|
||||||
|
events_table AS e
|
||||||
|
WHERE u.user_id = e.user_id AND
|
||||||
|
u.user_id IN
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
user_id
|
||||||
|
FROM
|
||||||
|
users_table
|
||||||
|
WHERE value_2 >= 5
|
||||||
|
AND EXISTS (SELECT user_id FROM events_table_local WHERE event_type > 1 AND event_type <= 3 AND value_3 > 1)
|
||||||
|
AND NOT EXISTS (SELECT user_id FROM events_table WHERE event_type > 3 AND event_type <= 4 AND value_3 > 1 AND user_id = users_table.user_id)
|
||||||
|
LIMIT 5
|
||||||
|
)
|
||||||
|
) t
|
||||||
|
GROUP BY user_id
|
||||||
|
) q
|
||||||
|
ORDER BY 2 DESC, 1;
|
||||||
|
DEBUG: generating subplan 8_1 for subquery SELECT user_id FROM subquery_local_tables.events_table_local WHERE ((event_type > 1) AND (event_type <= 3) AND (value_3 > (1)::double precision))
|
||||||
|
DEBUG: push down of limit count: 5
|
||||||
|
DEBUG: generating subplan 8_2 for subquery SELECT user_id FROM public.users_table WHERE ((value_2 >= 5) AND (EXISTS (SELECT intermediate_result.user_id FROM read_intermediate_result('8_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer))) AND (NOT (EXISTS (SELECT events_table.user_id FROM public.events_table WHERE ((events_table.event_type > 3) AND (events_table.event_type <= 4) AND (events_table.value_3 > (1)::double precision) AND (events_table.user_id = users_table.user_id)))))) LIMIT 5
|
||||||
|
user_id | array_length
|
||||||
|
---------+--------------
|
||||||
|
5 | 364
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- subquery (i.e., subquery_2) in WHERE->FROM should be replaced due to local tables
|
||||||
|
SELECT
|
||||||
|
user_id
|
||||||
|
FROM
|
||||||
|
users_table
|
||||||
|
WHERE
|
||||||
|
user_id IN
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
user_id
|
||||||
|
FROM (
|
||||||
|
SELECT
|
||||||
|
subquery_1.user_id, count_pay
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
(SELECT
|
||||||
|
users_table.user_id,
|
||||||
|
'action=>1' AS event,
|
||||||
|
events_table.time
|
||||||
|
FROM
|
||||||
|
users_table,
|
||||||
|
events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
users_table.user_id >= 1 AND
|
||||||
|
users_table.user_id <= 3 AND
|
||||||
|
events_table.event_type > 1 AND events_table.event_type < 3
|
||||||
|
)
|
||||||
|
UNION
|
||||||
|
(SELECT
|
||||||
|
users_table.user_id,
|
||||||
|
'action=>2' AS event,
|
||||||
|
events_table.time
|
||||||
|
FROM
|
||||||
|
users_table,
|
||||||
|
events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
users_table.user_id >= 1 AND
|
||||||
|
users_table.user_id <= 3 AND
|
||||||
|
events_table.event_type > 2 AND events_table.event_type < 4
|
||||||
|
)
|
||||||
|
) AS subquery_1
|
||||||
|
LEFT JOIN
|
||||||
|
(SELECT
|
||||||
|
user_id,
|
||||||
|
COUNT(*) AS count_pay
|
||||||
|
FROM
|
||||||
|
users_table_local
|
||||||
|
WHERE
|
||||||
|
user_id >= 1 AND
|
||||||
|
user_id <= 3 AND
|
||||||
|
users_table_local.value_1 > 3 AND users_table_local.value_1 < 5
|
||||||
|
GROUP BY
|
||||||
|
user_id
|
||||||
|
HAVING
|
||||||
|
COUNT(*) > 1
|
||||||
|
LIMIT 10
|
||||||
|
) AS subquery_2
|
||||||
|
ON
|
||||||
|
subquery_1.user_id = subquery_2.user_id
|
||||||
|
GROUP BY
|
||||||
|
subquery_1.user_id,
|
||||||
|
count_pay) AS subquery_top
|
||||||
|
GROUP BY
|
||||||
|
count_pay, user_id
|
||||||
|
)
|
||||||
|
GROUP BY user_id
|
||||||
|
HAVING count(*) > 1 AND sum(value_2) > 29
|
||||||
|
ORDER BY 1;
|
||||||
|
DEBUG: generating subplan 10_1 for subquery SELECT user_id, count(*) AS count_pay FROM subquery_local_tables.users_table_local WHERE ((user_id >= 1) AND (user_id <= 3) AND (value_1 > 3) AND (value_1 < 5)) GROUP BY user_id HAVING (count(*) > 1) LIMIT 10
|
||||||
|
user_id
|
||||||
|
---------
|
||||||
|
2
|
||||||
|
3
|
||||||
|
(2 rows)
|
||||||
|
|
||||||
|
SET client_min_messages TO DEFAULT;
|
||||||
|
DROP SCHEMA subquery_local_tables CASCADE;
|
||||||
|
NOTICE: drop cascades to 2 other objects
|
||||||
|
DETAIL: drop cascades to table users_table_local
|
||||||
|
drop cascades to table events_table_local
|
||||||
|
SET search_path TO public;
|
|
@ -0,0 +1,283 @@
|
||||||
|
-- ===================================================================
|
||||||
|
-- test recursive planning functionality on partitioned tables
|
||||||
|
-- ===================================================================
|
||||||
|
CREATE SCHEMA subquery_and_partitioning;
|
||||||
|
SET search_path TO subquery_and_partitioning, public;
|
||||||
|
CREATE TABLE users_table_local AS SELECT * FROM users_table;
|
||||||
|
CREATE TABLE events_table_local AS SELECT * FROM events_table;
|
||||||
|
CREATE TABLE partitioning_test(id int, value_1 int, time date) PARTITION BY RANGE (time);
|
||||||
|
|
||||||
|
-- create its partitions
|
||||||
|
CREATE TABLE partitioning_test_2017 PARTITION OF partitioning_test FOR VALUES FROM ('2017-01-01') TO ('2018-01-01');
|
||||||
|
CREATE TABLE partitioning_test_2010 PARTITION OF partitioning_test FOR VALUES FROM ('2010-01-01') TO ('2011-01-01');
|
||||||
|
-- load some data and distribute tables
|
||||||
|
INSERT INTO partitioning_test VALUES (1, 1, '2017-11-23');
|
||||||
|
INSERT INTO partitioning_test VALUES (2, 1, '2010-07-07');
|
||||||
|
INSERT INTO partitioning_test_2017 VALUES (3, 3, '2017-11-22');
|
||||||
|
INSERT INTO partitioning_test_2010 VALUES (4, 4, '2010-03-03');
|
||||||
|
-- distribute partitioned table
|
||||||
|
SET citus.shard_replication_factor TO 1;
|
||||||
|
SELECT create_distributed_table('partitioning_test', 'id');
|
||||||
|
NOTICE: Copying data from local table...
|
||||||
|
NOTICE: Copying data from local table...
|
||||||
|
create_distributed_table
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SET client_min_messages TO DEBUG1;
|
||||||
|
-- subplan for partitioned tables
|
||||||
|
SELECT
|
||||||
|
id
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
DISTINCT partitioning_test.id
|
||||||
|
FROM
|
||||||
|
partitioning_test
|
||||||
|
LIMIT 5
|
||||||
|
) as foo
|
||||||
|
ORDER BY 1 DESC;
|
||||||
|
DEBUG: push down of limit count: 5
|
||||||
|
DEBUG: generating subplan 3_1 for subquery SELECT DISTINCT id FROM subquery_and_partitioning.partitioning_test LIMIT 5
|
||||||
|
id
|
||||||
|
----
|
||||||
|
4
|
||||||
|
3
|
||||||
|
2
|
||||||
|
1
|
||||||
|
(4 rows)
|
||||||
|
|
||||||
|
-- final query is router on partitioned tables
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
DISTINCT partitioning_test.id
|
||||||
|
FROM
|
||||||
|
partitioning_test
|
||||||
|
LIMIT 5
|
||||||
|
) as foo,
|
||||||
|
(SELECT
|
||||||
|
DISTINCT partitioning_test.time
|
||||||
|
FROM
|
||||||
|
partitioning_test
|
||||||
|
LIMIT 5
|
||||||
|
) as bar
|
||||||
|
WHERE foo.id = date_part('day', bar.time)
|
||||||
|
ORDER BY 2 DESC, 1;
|
||||||
|
DEBUG: push down of limit count: 5
|
||||||
|
DEBUG: generating subplan 5_1 for subquery SELECT DISTINCT id FROM subquery_and_partitioning.partitioning_test LIMIT 5
|
||||||
|
DEBUG: push down of limit count: 5
|
||||||
|
DEBUG: generating subplan 5_2 for subquery SELECT DISTINCT "time" FROM subquery_and_partitioning.partitioning_test LIMIT 5
|
||||||
|
id | time
|
||||||
|
----+------------
|
||||||
|
3 | 03-03-2010
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- final query is real-time
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
DISTINCT partitioning_test.time
|
||||||
|
FROM
|
||||||
|
partitioning_test
|
||||||
|
ORDER BY 1 DESC
|
||||||
|
LIMIT 5
|
||||||
|
) as foo,
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
DISTINCT partitioning_test.id
|
||||||
|
FROM
|
||||||
|
partitioning_test
|
||||||
|
) as bar
|
||||||
|
WHERE date_part('day', foo.time) = bar.id
|
||||||
|
ORDER BY 2 DESC, 1 DESC
|
||||||
|
LIMIT 3;
|
||||||
|
DEBUG: push down of limit count: 5
|
||||||
|
DEBUG: generating subplan 8_1 for subquery SELECT DISTINCT "time" FROM subquery_and_partitioning.partitioning_test ORDER BY "time" DESC LIMIT 5
|
||||||
|
DEBUG: push down of limit count: 3
|
||||||
|
time | id
|
||||||
|
------------+----
|
||||||
|
03-03-2010 | 3
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- final query is real-time that is joined with partitioned table
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
DISTINCT partitioning_test.time
|
||||||
|
FROM
|
||||||
|
partitioning_test
|
||||||
|
ORDER BY 1 DESC
|
||||||
|
LIMIT 5
|
||||||
|
) as foo,
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
DISTINCT partitioning_test.id
|
||||||
|
FROM
|
||||||
|
partitioning_test
|
||||||
|
) as bar,
|
||||||
|
partitioning_test
|
||||||
|
WHERE date_part('day', foo.time) = bar.id AND partitioning_test.id = bar.id
|
||||||
|
ORDER BY 2 DESC, 1 DESC
|
||||||
|
LIMIT 3;
|
||||||
|
DEBUG: push down of limit count: 5
|
||||||
|
DEBUG: generating subplan 10_1 for subquery SELECT DISTINCT "time" FROM subquery_and_partitioning.partitioning_test ORDER BY "time" DESC LIMIT 5
|
||||||
|
DEBUG: push down of limit count: 3
|
||||||
|
time | id | id | value_1 | time
|
||||||
|
------------+----+----+---------+------------
|
||||||
|
03-03-2010 | 3 | 3 | 3 | 11-22-2017
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- subquery in WHERE clause
|
||||||
|
SELECT DISTINCT id
|
||||||
|
FROM partitioning_test
|
||||||
|
WHERE
|
||||||
|
id IN (SELECT DISTINCT date_part('day', time) FROM partitioning_test);
|
||||||
|
DEBUG: generating subplan 12_1 for subquery SELECT DISTINCT date_part('day'::text, "time") AS date_part FROM subquery_and_partitioning.partitioning_test
|
||||||
|
id
|
||||||
|
----
|
||||||
|
3
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- repartition subquery
|
||||||
|
SET citus.enable_repartition_joins to ON;
|
||||||
|
SELECT
|
||||||
|
count(*)
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT DISTINCT p1.value_1 FROM partitioning_test as p1, partitioning_test as p2 WHERE p1.id = p2.value_1
|
||||||
|
) as foo,
|
||||||
|
(
|
||||||
|
SELECT user_id FROM users_table
|
||||||
|
) as bar
|
||||||
|
WHERE foo.value_1 = bar.user_id;
|
||||||
|
DEBUG: cannot use real time executor with repartition jobs
|
||||||
|
HINT: Since you enabled citus.enable_repartition_joins Citus chose to use task-tracker.
|
||||||
|
DEBUG: generating subplan 14_1 for subquery SELECT DISTINCT p1.value_1 FROM subquery_and_partitioning.partitioning_test p1, subquery_and_partitioning.partitioning_test p2 WHERE (p1.id = p2.value_1)
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
47
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SET citus.enable_repartition_joins to OFF;
|
||||||
|
-- subquery, cte, view and non-partitioned tables
|
||||||
|
CREATE VIEW subquery_and_ctes AS
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
WITH cte AS (
|
||||||
|
WITH local_cte AS (
|
||||||
|
SELECT * FROM users_table_local
|
||||||
|
),
|
||||||
|
dist_cte AS (
|
||||||
|
SELECT
|
||||||
|
user_id
|
||||||
|
FROM
|
||||||
|
events_table,
|
||||||
|
(SELECT DISTINCT value_1 FROM partitioning_test OFFSET 0) as foo
|
||||||
|
WHERE
|
||||||
|
events_table.user_id = foo.value_1 AND
|
||||||
|
events_table.user_id IN (SELECT DISTINCT value_1 FROM users_table ORDER BY 1 LIMIT 3)
|
||||||
|
)
|
||||||
|
SELECT dist_cte.user_id FROM local_cte join dist_cte on dist_cte.user_id=local_cte.user_id
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
count(*) as cnt
|
||||||
|
FROM
|
||||||
|
cte,
|
||||||
|
(SELECT
|
||||||
|
DISTINCT events_table.user_id
|
||||||
|
FROM
|
||||||
|
partitioning_test, events_table
|
||||||
|
WHERE
|
||||||
|
events_table.user_id = partitioning_test.id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
ORDER BY 1 DESC LIMIT 5
|
||||||
|
) as foo
|
||||||
|
WHERE foo.user_id = cte.user_id
|
||||||
|
) as foo, users_table WHERE foo.cnt > users_table.value_2;
|
||||||
|
SELECT * FROM subquery_and_ctes
|
||||||
|
ORDER BY 3 DESC, 1 DESC, 2 DESC, 4 DESC
|
||||||
|
LIMIT 5;
|
||||||
|
DEBUG: generating subplan 16_1 for CTE cte: WITH local_cte AS (SELECT users_table_local.user_id, users_table_local."time", users_table_local.value_1, users_table_local.value_2, users_table_local.value_3, users_table_local.value_4 FROM subquery_and_partitioning.users_table_local), dist_cte AS (SELECT events_table.user_id FROM public.events_table, (SELECT DISTINCT partitioning_test.value_1 FROM subquery_and_partitioning.partitioning_test OFFSET 0) foo WHERE ((events_table.user_id = foo.value_1) AND (events_table.user_id IN (SELECT DISTINCT users_table.value_1 FROM public.users_table ORDER BY users_table.value_1 LIMIT 3)))) SELECT dist_cte.user_id FROM (local_cte JOIN dist_cte ON ((dist_cte.user_id = local_cte.user_id)))
|
||||||
|
DEBUG: generating subplan 17_1 for CTE local_cte: SELECT user_id, "time", value_1, value_2, value_3, value_4 FROM subquery_and_partitioning.users_table_local
|
||||||
|
DEBUG: generating subplan 17_2 for CTE dist_cte: SELECT events_table.user_id FROM public.events_table, (SELECT DISTINCT partitioning_test.value_1 FROM subquery_and_partitioning.partitioning_test OFFSET 0) foo WHERE ((events_table.user_id = foo.value_1) AND (events_table.user_id IN (SELECT DISTINCT users_table.value_1 FROM public.users_table ORDER BY users_table.value_1 LIMIT 3)))
|
||||||
|
DEBUG: push down of limit count: 3
|
||||||
|
DEBUG: generating subplan 18_1 for subquery SELECT DISTINCT value_1 FROM public.users_table ORDER BY value_1 LIMIT 3
|
||||||
|
DEBUG: generating subplan 18_2 for subquery SELECT DISTINCT value_1 FROM subquery_and_partitioning.partitioning_test OFFSET 0
|
||||||
|
DEBUG: push down of limit count: 5
|
||||||
|
DEBUG: generating subplan 16_2 for subquery SELECT DISTINCT events_table.user_id FROM subquery_and_partitioning.partitioning_test, public.events_table WHERE ((events_table.user_id = partitioning_test.id) AND (events_table.event_type = ANY (ARRAY[1, 2, 3, 4]))) ORDER BY events_table.user_id DESC LIMIT 5
|
||||||
|
DEBUG: generating subplan 16_3 for subquery SELECT count(*) AS cnt FROM (SELECT intermediate_result.user_id FROM read_intermediate_result('16_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) cte, (SELECT intermediate_result.user_id FROM read_intermediate_result('16_2'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) foo WHERE (foo.user_id = cte.user_id)
|
||||||
|
DEBUG: push down of limit count: 5
|
||||||
|
cnt | user_id | time | value_1 | value_2 | value_3 | value_4
|
||||||
|
-----+---------+---------------------------------+---------+---------+---------+---------
|
||||||
|
105 | 1 | Thu Nov 23 17:30:34.635085 2017 | 3 | 4 | 4 |
|
||||||
|
105 | 1 | Thu Nov 23 17:23:03.441394 2017 | 5 | 4 | 3 |
|
||||||
|
105 | 3 | Thu Nov 23 17:18:51.048758 2017 | 1 | 5 | 5 |
|
||||||
|
105 | 3 | Thu Nov 23 17:10:35.959913 2017 | 4 | 3 | 1 |
|
||||||
|
105 | 5 | Thu Nov 23 16:48:32.08896 2017 | 5 | 2 | 1 |
|
||||||
|
(5 rows)
|
||||||
|
|
||||||
|
-- deep subquery, partitioned and non-partitioned tables together
|
||||||
|
SELECT count(*)
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT avg(min) FROM
|
||||||
|
(
|
||||||
|
SELECT min(partitioning_test.value_1) FROM
|
||||||
|
(
|
||||||
|
SELECT avg(event_type) as avg_ev_type FROM
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
max(value_1) as mx_val_1
|
||||||
|
FROM (
|
||||||
|
SELECT
|
||||||
|
avg(event_type) as avg
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
cnt
|
||||||
|
FROM
|
||||||
|
(SELECT count(*) as cnt, value_1 FROM partitioning_test GROUP BY value_1) as level_1, users_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = level_1.cnt
|
||||||
|
) as level_2, events_table
|
||||||
|
WHERE events_table.user_id = level_2.cnt
|
||||||
|
GROUP BY level_2.cnt
|
||||||
|
) as level_3, users_table
|
||||||
|
WHERE user_id = level_3.avg
|
||||||
|
GROUP BY level_3.avg
|
||||||
|
) as level_4, events_table
|
||||||
|
WHERE level_4.mx_val_1 = events_table.user_id
|
||||||
|
GROUP BY level_4.mx_val_1
|
||||||
|
) as level_5, partitioning_test
|
||||||
|
WHERE
|
||||||
|
level_5.avg_ev_type = partitioning_test.id
|
||||||
|
GROUP BY
|
||||||
|
level_5.avg_ev_type
|
||||||
|
) as level_6, users_table WHERE users_table.user_id = level_6.min
|
||||||
|
GROUP BY users_table.value_1
|
||||||
|
) as bar;
|
||||||
|
DEBUG: generating subplan 23_1 for subquery SELECT count(*) AS cnt, value_1 FROM subquery_and_partitioning.partitioning_test GROUP BY value_1
|
||||||
|
DEBUG: generating subplan 23_2 for subquery SELECT avg(events_table.event_type) AS avg FROM (SELECT level_1.cnt FROM (SELECT intermediate_result.cnt, intermediate_result.value_1 FROM read_intermediate_result('23_1'::text, 'binary'::citus_copy_format) intermediate_result(cnt bigint, value_1 integer)) level_1, public.users_table WHERE (users_table.user_id = level_1.cnt)) level_2, public.events_table WHERE (events_table.user_id = level_2.cnt) GROUP BY level_2.cnt
|
||||||
|
DEBUG: generating subplan 23_3 for subquery SELECT max(users_table.value_1) AS mx_val_1 FROM (SELECT intermediate_result.avg FROM read_intermediate_result('23_2'::text, 'binary'::citus_copy_format) intermediate_result(avg numeric)) level_3, public.users_table WHERE ((users_table.user_id)::numeric = level_3.avg) GROUP BY level_3.avg
|
||||||
|
DEBUG: generating subplan 23_4 for subquery SELECT avg(events_table.event_type) AS avg_ev_type FROM (SELECT intermediate_result.mx_val_1 FROM read_intermediate_result('23_3'::text, 'binary'::citus_copy_format) intermediate_result(mx_val_1 integer)) level_4, public.events_table WHERE (level_4.mx_val_1 = events_table.user_id) GROUP BY level_4.mx_val_1
|
||||||
|
DEBUG: generating subplan 23_5 for subquery SELECT min(partitioning_test.value_1) AS min FROM (SELECT intermediate_result.avg_ev_type FROM read_intermediate_result('23_4'::text, 'binary'::citus_copy_format) intermediate_result(avg_ev_type numeric)) level_5, subquery_and_partitioning.partitioning_test WHERE (level_5.avg_ev_type = (partitioning_test.id)::numeric) GROUP BY level_5.avg_ev_type
|
||||||
|
DEBUG: generating subplan 23_6 for subquery SELECT avg(level_6.min) AS avg FROM (SELECT intermediate_result.min FROM read_intermediate_result('23_5'::text, 'binary'::citus_copy_format) intermediate_result(min integer)) level_6, public.users_table WHERE (users_table.user_id = level_6.min) GROUP BY users_table.value_1
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
0
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SET client_min_messages TO DEFAULT;
|
||||||
|
DROP SCHEMA subquery_and_partitioning CASCADE;
|
||||||
|
NOTICE: drop cascades to 4 other objects
|
||||||
|
DETAIL: drop cascades to table users_table_local
|
||||||
|
drop cascades to table events_table_local
|
||||||
|
drop cascades to table partitioning_test
|
||||||
|
drop cascades to view subquery_and_ctes
|
||||||
|
SET search_path TO public;
|
|
@ -0,0 +1,246 @@
|
||||||
|
-- ===================================================================
|
||||||
|
-- test recursive planning functionality on partitioned tables
|
||||||
|
-- ===================================================================
|
||||||
|
CREATE SCHEMA subquery_and_partitioning;
|
||||||
|
SET search_path TO subquery_and_partitioning, public;
|
||||||
|
CREATE TABLE users_table_local AS SELECT * FROM users_table;
|
||||||
|
CREATE TABLE events_table_local AS SELECT * FROM events_table;
|
||||||
|
CREATE TABLE partitioning_test(id int, value_1 int, time date) PARTITION BY RANGE (time);
|
||||||
|
ERROR: syntax error at or near "PARTITION"
|
||||||
|
LINE 1: ...partitioning_test(id int, value_1 int, time date) PARTITION ...
|
||||||
|
^
|
||||||
|
|
||||||
|
-- create its partitions
|
||||||
|
CREATE TABLE partitioning_test_2017 PARTITION OF partitioning_test FOR VALUES FROM ('2017-01-01') TO ('2018-01-01');
|
||||||
|
ERROR: syntax error at or near "PARTITION"
|
||||||
|
LINE 1: CREATE TABLE partitioning_test_2017 PARTITION OF partitionin...
|
||||||
|
^
|
||||||
|
CREATE TABLE partitioning_test_2010 PARTITION OF partitioning_test FOR VALUES FROM ('2010-01-01') TO ('2011-01-01');
|
||||||
|
ERROR: syntax error at or near "PARTITION"
|
||||||
|
LINE 1: CREATE TABLE partitioning_test_2010 PARTITION OF partitionin...
|
||||||
|
^
|
||||||
|
-- load some data and distribute tables
|
||||||
|
INSERT INTO partitioning_test VALUES (1, 1, '2017-11-23');
|
||||||
|
ERROR: relation "partitioning_test" does not exist
|
||||||
|
LINE 1: INSERT INTO partitioning_test VALUES (1, 1, '2017-11-23');
|
||||||
|
^
|
||||||
|
INSERT INTO partitioning_test VALUES (2, 1, '2010-07-07');
|
||||||
|
ERROR: relation "partitioning_test" does not exist
|
||||||
|
LINE 1: INSERT INTO partitioning_test VALUES (2, 1, '2010-07-07');
|
||||||
|
^
|
||||||
|
INSERT INTO partitioning_test_2017 VALUES (3, 3, '2017-11-22');
|
||||||
|
ERROR: relation "partitioning_test_2017" does not exist
|
||||||
|
LINE 1: INSERT INTO partitioning_test_2017 VALUES (3, 3, '2017-11-22...
|
||||||
|
^
|
||||||
|
INSERT INTO partitioning_test_2010 VALUES (4, 4, '2010-03-03');
|
||||||
|
ERROR: relation "partitioning_test_2010" does not exist
|
||||||
|
LINE 1: INSERT INTO partitioning_test_2010 VALUES (4, 4, '2010-03-03...
|
||||||
|
^
|
||||||
|
-- distribute partitioned table
|
||||||
|
SET citus.shard_replication_factor TO 1;
|
||||||
|
SELECT create_distributed_table('partitioning_test', 'id');
|
||||||
|
ERROR: relation "partitioning_test" does not exist
|
||||||
|
LINE 1: SELECT create_distributed_table('partitioning_test', 'id');
|
||||||
|
^
|
||||||
|
SET client_min_messages TO DEBUG1;
|
||||||
|
-- subplan for partitioned tables
|
||||||
|
SELECT
|
||||||
|
id
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
DISTINCT partitioning_test.id
|
||||||
|
FROM
|
||||||
|
partitioning_test
|
||||||
|
LIMIT 5
|
||||||
|
) as foo
|
||||||
|
ORDER BY 1 DESC;
|
||||||
|
ERROR: relation "partitioning_test" does not exist
|
||||||
|
LINE 7: partitioning_test
|
||||||
|
^
|
||||||
|
-- final query is router on partitioned tables
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
DISTINCT partitioning_test.id
|
||||||
|
FROM
|
||||||
|
partitioning_test
|
||||||
|
LIMIT 5
|
||||||
|
) as foo,
|
||||||
|
(SELECT
|
||||||
|
DISTINCT partitioning_test.time
|
||||||
|
FROM
|
||||||
|
partitioning_test
|
||||||
|
LIMIT 5
|
||||||
|
) as bar
|
||||||
|
WHERE foo.id = date_part('day', bar.time)
|
||||||
|
ORDER BY 2 DESC, 1;
|
||||||
|
ERROR: relation "partitioning_test" does not exist
|
||||||
|
LINE 7: partitioning_test
|
||||||
|
^
|
||||||
|
-- final query is real-time
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
DISTINCT partitioning_test.time
|
||||||
|
FROM
|
||||||
|
partitioning_test
|
||||||
|
ORDER BY 1 DESC
|
||||||
|
LIMIT 5
|
||||||
|
) as foo,
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
DISTINCT partitioning_test.id
|
||||||
|
FROM
|
||||||
|
partitioning_test
|
||||||
|
) as bar
|
||||||
|
WHERE date_part('day', foo.time) = bar.id
|
||||||
|
ORDER BY 2 DESC, 1 DESC
|
||||||
|
LIMIT 3;
|
||||||
|
ERROR: relation "partitioning_test" does not exist
|
||||||
|
LINE 7: partitioning_test
|
||||||
|
^
|
||||||
|
-- final query is real-time that is joined with partitioned table
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
DISTINCT partitioning_test.time
|
||||||
|
FROM
|
||||||
|
partitioning_test
|
||||||
|
ORDER BY 1 DESC
|
||||||
|
LIMIT 5
|
||||||
|
) as foo,
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
DISTINCT partitioning_test.id
|
||||||
|
FROM
|
||||||
|
partitioning_test
|
||||||
|
) as bar,
|
||||||
|
partitioning_test
|
||||||
|
WHERE date_part('day', foo.time) = bar.id AND partitioning_test.id = bar.id
|
||||||
|
ORDER BY 2 DESC, 1 DESC
|
||||||
|
LIMIT 3;
|
||||||
|
ERROR: relation "partitioning_test" does not exist
|
||||||
|
LINE 7: partitioning_test
|
||||||
|
^
|
||||||
|
-- subquery in WHERE clause
|
||||||
|
SELECT DISTINCT id
|
||||||
|
FROM partitioning_test
|
||||||
|
WHERE
|
||||||
|
id IN (SELECT DISTINCT date_part('day', time) FROM partitioning_test);
|
||||||
|
ERROR: relation "partitioning_test" does not exist
|
||||||
|
LINE 2: FROM partitioning_test
|
||||||
|
^
|
||||||
|
-- repartition subquery
|
||||||
|
SET citus.enable_repartition_joins to ON;
|
||||||
|
SELECT
|
||||||
|
count(*)
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT DISTINCT p1.value_1 FROM partitioning_test as p1, partitioning_test as p2 WHERE p1.id = p2.value_1
|
||||||
|
) as foo,
|
||||||
|
(
|
||||||
|
SELECT user_id FROM users_table
|
||||||
|
) as bar
|
||||||
|
WHERE foo.value_1 = bar.user_id;
|
||||||
|
ERROR: relation "partitioning_test" does not exist
|
||||||
|
LINE 5: SELECT DISTINCT p1.value_1 FROM partitioning_test as p1, pa...
|
||||||
|
^
|
||||||
|
SET citus.enable_repartition_joins to OFF;
|
||||||
|
-- subquery, cte, view and non-partitioned tables
|
||||||
|
CREATE VIEW subquery_and_ctes AS
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
WITH cte AS (
|
||||||
|
WITH local_cte AS (
|
||||||
|
SELECT * FROM users_table_local
|
||||||
|
),
|
||||||
|
dist_cte AS (
|
||||||
|
SELECT
|
||||||
|
user_id
|
||||||
|
FROM
|
||||||
|
events_table,
|
||||||
|
(SELECT DISTINCT value_1 FROM partitioning_test OFFSET 0) as foo
|
||||||
|
WHERE
|
||||||
|
events_table.user_id = foo.value_1 AND
|
||||||
|
events_table.user_id IN (SELECT DISTINCT value_1 FROM users_table ORDER BY 1 LIMIT 3)
|
||||||
|
)
|
||||||
|
SELECT dist_cte.user_id FROM local_cte join dist_cte on dist_cte.user_id=local_cte.user_id
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
count(*) as cnt
|
||||||
|
FROM
|
||||||
|
cte,
|
||||||
|
(SELECT
|
||||||
|
DISTINCT events_table.user_id
|
||||||
|
FROM
|
||||||
|
partitioning_test, events_table
|
||||||
|
WHERE
|
||||||
|
events_table.user_id = partitioning_test.id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
ORDER BY 1 DESC LIMIT 5
|
||||||
|
) as foo
|
||||||
|
WHERE foo.user_id = cte.user_id
|
||||||
|
) as foo, users_table WHERE foo.cnt > users_table.value_2;
|
||||||
|
ERROR: relation "partitioning_test" does not exist
|
||||||
|
LINE 15: (SELECT DISTINCT value_1 FROM partitioning_test OFFSET 0)...
|
||||||
|
^
|
||||||
|
SELECT * FROM subquery_and_ctes
|
||||||
|
ORDER BY 3 DESC, 1 DESC, 2 DESC, 4 DESC
|
||||||
|
LIMIT 5;
|
||||||
|
ERROR: relation "subquery_and_ctes" does not exist
|
||||||
|
LINE 1: SELECT * FROM subquery_and_ctes
|
||||||
|
^
|
||||||
|
-- deep subquery, partitioned and non-partitioned tables together
|
||||||
|
SELECT count(*)
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT avg(min) FROM
|
||||||
|
(
|
||||||
|
SELECT min(partitioning_test.value_1) FROM
|
||||||
|
(
|
||||||
|
SELECT avg(event_type) as avg_ev_type FROM
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
max(value_1) as mx_val_1
|
||||||
|
FROM (
|
||||||
|
SELECT
|
||||||
|
avg(event_type) as avg
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
cnt
|
||||||
|
FROM
|
||||||
|
(SELECT count(*) as cnt, value_1 FROM partitioning_test GROUP BY value_1) as level_1, users_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = level_1.cnt
|
||||||
|
) as level_2, events_table
|
||||||
|
WHERE events_table.user_id = level_2.cnt
|
||||||
|
GROUP BY level_2.cnt
|
||||||
|
) as level_3, users_table
|
||||||
|
WHERE user_id = level_3.avg
|
||||||
|
GROUP BY level_3.avg
|
||||||
|
) as level_4, events_table
|
||||||
|
WHERE level_4.mx_val_1 = events_table.user_id
|
||||||
|
GROUP BY level_4.mx_val_1
|
||||||
|
) as level_5, partitioning_test
|
||||||
|
WHERE
|
||||||
|
level_5.avg_ev_type = partitioning_test.id
|
||||||
|
GROUP BY
|
||||||
|
level_5.avg_ev_type
|
||||||
|
) as level_6, users_table WHERE users_table.user_id = level_6.min
|
||||||
|
GROUP BY users_table.value_1
|
||||||
|
) as bar;
|
||||||
|
ERROR: relation "partitioning_test" does not exist
|
||||||
|
LINE 20: (SELECT count(*) as cnt, value_1 FROM partitioning_...
|
||||||
|
^
|
||||||
|
SET client_min_messages TO DEFAULT;
|
||||||
|
DROP SCHEMA subquery_and_partitioning CASCADE;
|
||||||
|
NOTICE: drop cascades to 2 other objects
|
||||||
|
DETAIL: drop cascades to table users_table_local
|
||||||
|
drop cascades to table events_table_local
|
||||||
|
SET search_path TO public;
|
|
@ -0,0 +1,285 @@
|
||||||
|
-- ===================================================================
|
||||||
|
-- test recursive planning functionality on prepared statements
|
||||||
|
-- ===================================================================
|
||||||
|
CREATE SCHEMA subquery_prepared_statements;
|
||||||
|
SET search_path TO subquery_prepared_statements, public;
|
||||||
|
CREATE TYPE xy AS (x int, y int);
|
||||||
|
SELECT run_command_on_workers('CREATE SCHEMA subquery_prepared_statements');
|
||||||
|
run_command_on_workers
|
||||||
|
-------------------------------------
|
||||||
|
(localhost,57637,t,"CREATE SCHEMA")
|
||||||
|
(localhost,57638,t,"CREATE SCHEMA")
|
||||||
|
(2 rows)
|
||||||
|
|
||||||
|
SELECT run_command_on_workers('CREATE TYPE subquery_prepared_statements.xy AS (x int, y int)');
|
||||||
|
run_command_on_workers
|
||||||
|
-----------------------------------
|
||||||
|
(localhost,57637,t,"CREATE TYPE")
|
||||||
|
(localhost,57638,t,"CREATE TYPE")
|
||||||
|
(2 rows)
|
||||||
|
|
||||||
|
SET client_min_messages TO DEBUG1;
|
||||||
|
PREPARE subquery_prepare_without_param AS
|
||||||
|
SELECT
|
||||||
|
DISTINCT values_of_subquery
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
DISTINCT (users_table.user_id, events_table.event_type)::xy as values_of_subquery
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
ORDER BY 1 DESC LIMIT 5
|
||||||
|
) as foo
|
||||||
|
ORDER BY 1 DESC;
|
||||||
|
PREPARE subquery_prepare_param_on_partkey(int) AS
|
||||||
|
SELECT
|
||||||
|
DISTINCT values_of_subquery
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
DISTINCT (users_table.user_id, events_table.event_type)::xy as values_of_subquery
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
(users_table.user_id = $1 OR users_table.user_id = 2) AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
ORDER BY 1 DESC LIMIT 5
|
||||||
|
) as foo
|
||||||
|
ORDER BY 1 DESC;
|
||||||
|
PREPARE subquery_prepare_param_non_partkey(int) AS
|
||||||
|
SELECT
|
||||||
|
DISTINCT values_of_subquery
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
DISTINCT (users_table.user_id, events_table.event_type)::xy as values_of_subquery
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type = $1
|
||||||
|
ORDER BY 1 DESC LIMIT 5
|
||||||
|
) as foo
|
||||||
|
ORDER BY 1 DESC;
|
||||||
|
-- execute each test with 6 times
|
||||||
|
EXECUTE subquery_prepare_without_param;
|
||||||
|
DEBUG: push down of limit count: 5
|
||||||
|
DEBUG: generating subplan 1_1 for subquery SELECT DISTINCT ROW(users_table.user_id, events_table.event_type)::subquery_prepared_statements.xy AS values_of_subquery FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.user_id) AND (events_table.event_type = ANY (ARRAY[1, 2, 3, 4]))) ORDER BY ROW(users_table.user_id, events_table.event_type)::subquery_prepared_statements.xy DESC LIMIT 5
|
||||||
|
values_of_subquery
|
||||||
|
--------------------
|
||||||
|
(6,4)
|
||||||
|
(6,3)
|
||||||
|
(6,2)
|
||||||
|
(6,1)
|
||||||
|
(5,4)
|
||||||
|
(5 rows)
|
||||||
|
|
||||||
|
EXECUTE subquery_prepare_without_param;
|
||||||
|
values_of_subquery
|
||||||
|
--------------------
|
||||||
|
(6,4)
|
||||||
|
(6,3)
|
||||||
|
(6,2)
|
||||||
|
(6,1)
|
||||||
|
(5,4)
|
||||||
|
(5 rows)
|
||||||
|
|
||||||
|
EXECUTE subquery_prepare_without_param;
|
||||||
|
values_of_subquery
|
||||||
|
--------------------
|
||||||
|
(6,4)
|
||||||
|
(6,3)
|
||||||
|
(6,2)
|
||||||
|
(6,1)
|
||||||
|
(5,4)
|
||||||
|
(5 rows)
|
||||||
|
|
||||||
|
EXECUTE subquery_prepare_without_param;
|
||||||
|
values_of_subquery
|
||||||
|
--------------------
|
||||||
|
(6,4)
|
||||||
|
(6,3)
|
||||||
|
(6,2)
|
||||||
|
(6,1)
|
||||||
|
(5,4)
|
||||||
|
(5 rows)
|
||||||
|
|
||||||
|
EXECUTE subquery_prepare_without_param;
|
||||||
|
values_of_subquery
|
||||||
|
--------------------
|
||||||
|
(6,4)
|
||||||
|
(6,3)
|
||||||
|
(6,2)
|
||||||
|
(6,1)
|
||||||
|
(5,4)
|
||||||
|
(5 rows)
|
||||||
|
|
||||||
|
EXECUTE subquery_prepare_without_param;
|
||||||
|
values_of_subquery
|
||||||
|
--------------------
|
||||||
|
(6,4)
|
||||||
|
(6,3)
|
||||||
|
(6,2)
|
||||||
|
(6,1)
|
||||||
|
(5,4)
|
||||||
|
(5 rows)
|
||||||
|
|
||||||
|
EXECUTE subquery_prepare_without_param;
|
||||||
|
values_of_subquery
|
||||||
|
--------------------
|
||||||
|
(6,4)
|
||||||
|
(6,3)
|
||||||
|
(6,2)
|
||||||
|
(6,1)
|
||||||
|
(5,4)
|
||||||
|
(5 rows)
|
||||||
|
|
||||||
|
EXECUTE subquery_prepare_param_on_partkey(1);
|
||||||
|
DEBUG: push down of limit count: 5
|
||||||
|
DEBUG: generating subplan 3_1 for subquery SELECT DISTINCT ROW(users_table.user_id, events_table.event_type)::subquery_prepared_statements.xy AS values_of_subquery FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.user_id) AND ((users_table.user_id = 1) OR (users_table.user_id = 2)) AND (events_table.event_type = ANY (ARRAY[1, 2, 3, 4]))) ORDER BY ROW(users_table.user_id, events_table.event_type)::subquery_prepared_statements.xy DESC LIMIT 5
|
||||||
|
values_of_subquery
|
||||||
|
--------------------
|
||||||
|
(2,4)
|
||||||
|
(2,3)
|
||||||
|
(2,2)
|
||||||
|
(2,1)
|
||||||
|
(1,4)
|
||||||
|
(5 rows)
|
||||||
|
|
||||||
|
EXECUTE subquery_prepare_param_on_partkey(1);
|
||||||
|
DEBUG: push down of limit count: 5
|
||||||
|
DEBUG: generating subplan 5_1 for subquery SELECT DISTINCT ROW(users_table.user_id, events_table.event_type)::subquery_prepared_statements.xy AS values_of_subquery FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.user_id) AND ((users_table.user_id = 1) OR (users_table.user_id = 2)) AND (events_table.event_type = ANY (ARRAY[1, 2, 3, 4]))) ORDER BY ROW(users_table.user_id, events_table.event_type)::subquery_prepared_statements.xy DESC LIMIT 5
|
||||||
|
values_of_subquery
|
||||||
|
--------------------
|
||||||
|
(2,4)
|
||||||
|
(2,3)
|
||||||
|
(2,2)
|
||||||
|
(2,1)
|
||||||
|
(1,4)
|
||||||
|
(5 rows)
|
||||||
|
|
||||||
|
EXECUTE subquery_prepare_param_on_partkey(1);
|
||||||
|
DEBUG: push down of limit count: 5
|
||||||
|
DEBUG: generating subplan 7_1 for subquery SELECT DISTINCT ROW(users_table.user_id, events_table.event_type)::subquery_prepared_statements.xy AS values_of_subquery FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.user_id) AND ((users_table.user_id = 1) OR (users_table.user_id = 2)) AND (events_table.event_type = ANY (ARRAY[1, 2, 3, 4]))) ORDER BY ROW(users_table.user_id, events_table.event_type)::subquery_prepared_statements.xy DESC LIMIT 5
|
||||||
|
values_of_subquery
|
||||||
|
--------------------
|
||||||
|
(2,4)
|
||||||
|
(2,3)
|
||||||
|
(2,2)
|
||||||
|
(2,1)
|
||||||
|
(1,4)
|
||||||
|
(5 rows)
|
||||||
|
|
||||||
|
EXECUTE subquery_prepare_param_on_partkey(1);
|
||||||
|
DEBUG: push down of limit count: 5
|
||||||
|
DEBUG: generating subplan 9_1 for subquery SELECT DISTINCT ROW(users_table.user_id, events_table.event_type)::subquery_prepared_statements.xy AS values_of_subquery FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.user_id) AND ((users_table.user_id = 1) OR (users_table.user_id = 2)) AND (events_table.event_type = ANY (ARRAY[1, 2, 3, 4]))) ORDER BY ROW(users_table.user_id, events_table.event_type)::subquery_prepared_statements.xy DESC LIMIT 5
|
||||||
|
values_of_subquery
|
||||||
|
--------------------
|
||||||
|
(2,4)
|
||||||
|
(2,3)
|
||||||
|
(2,2)
|
||||||
|
(2,1)
|
||||||
|
(1,4)
|
||||||
|
(5 rows)
|
||||||
|
|
||||||
|
EXECUTE subquery_prepare_param_on_partkey(1);
|
||||||
|
DEBUG: push down of limit count: 5
|
||||||
|
DEBUG: generating subplan 11_1 for subquery SELECT DISTINCT ROW(users_table.user_id, events_table.event_type)::subquery_prepared_statements.xy AS values_of_subquery FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.user_id) AND ((users_table.user_id = 1) OR (users_table.user_id = 2)) AND (events_table.event_type = ANY (ARRAY[1, 2, 3, 4]))) ORDER BY ROW(users_table.user_id, events_table.event_type)::subquery_prepared_statements.xy DESC LIMIT 5
|
||||||
|
values_of_subquery
|
||||||
|
--------------------
|
||||||
|
(2,4)
|
||||||
|
(2,3)
|
||||||
|
(2,2)
|
||||||
|
(2,1)
|
||||||
|
(1,4)
|
||||||
|
(5 rows)
|
||||||
|
|
||||||
|
EXECUTE subquery_prepare_param_on_partkey(1);
|
||||||
|
DEBUG: push down of limit count: 5
|
||||||
|
DEBUG: generating subplan 14_1 for subquery SELECT DISTINCT ROW(users_table.user_id, events_table.event_type)::subquery_prepared_statements.xy AS values_of_subquery FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.user_id) AND ((users_table.user_id = 1) OR (users_table.user_id = 2)) AND (events_table.event_type = ANY (ARRAY[1, 2, 3, 4]))) ORDER BY ROW(users_table.user_id, events_table.event_type)::subquery_prepared_statements.xy DESC LIMIT 5
|
||||||
|
values_of_subquery
|
||||||
|
--------------------
|
||||||
|
(2,4)
|
||||||
|
(2,3)
|
||||||
|
(2,2)
|
||||||
|
(2,1)
|
||||||
|
(1,4)
|
||||||
|
(5 rows)
|
||||||
|
|
||||||
|
EXECUTE subquery_prepare_param_non_partkey(1);
|
||||||
|
DEBUG: push down of limit count: 5
|
||||||
|
DEBUG: generating subplan 16_1 for subquery SELECT DISTINCT ROW(users_table.user_id, events_table.event_type)::subquery_prepared_statements.xy AS values_of_subquery FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.user_id) AND (events_table.event_type = 1)) ORDER BY ROW(users_table.user_id, events_table.event_type)::subquery_prepared_statements.xy DESC LIMIT 5
|
||||||
|
values_of_subquery
|
||||||
|
--------------------
|
||||||
|
(6,1)
|
||||||
|
(5,1)
|
||||||
|
(4,1)
|
||||||
|
(3,1)
|
||||||
|
(2,1)
|
||||||
|
(5 rows)
|
||||||
|
|
||||||
|
EXECUTE subquery_prepare_param_non_partkey(1);
|
||||||
|
DEBUG: push down of limit count: 5
|
||||||
|
DEBUG: generating subplan 18_1 for subquery SELECT DISTINCT ROW(users_table.user_id, events_table.event_type)::subquery_prepared_statements.xy AS values_of_subquery FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.user_id) AND (events_table.event_type = 1)) ORDER BY ROW(users_table.user_id, events_table.event_type)::subquery_prepared_statements.xy DESC LIMIT 5
|
||||||
|
values_of_subquery
|
||||||
|
--------------------
|
||||||
|
(6,1)
|
||||||
|
(5,1)
|
||||||
|
(4,1)
|
||||||
|
(3,1)
|
||||||
|
(2,1)
|
||||||
|
(5 rows)
|
||||||
|
|
||||||
|
EXECUTE subquery_prepare_param_non_partkey(1);
|
||||||
|
DEBUG: push down of limit count: 5
|
||||||
|
DEBUG: generating subplan 20_1 for subquery SELECT DISTINCT ROW(users_table.user_id, events_table.event_type)::subquery_prepared_statements.xy AS values_of_subquery FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.user_id) AND (events_table.event_type = 1)) ORDER BY ROW(users_table.user_id, events_table.event_type)::subquery_prepared_statements.xy DESC LIMIT 5
|
||||||
|
values_of_subquery
|
||||||
|
--------------------
|
||||||
|
(6,1)
|
||||||
|
(5,1)
|
||||||
|
(4,1)
|
||||||
|
(3,1)
|
||||||
|
(2,1)
|
||||||
|
(5 rows)
|
||||||
|
|
||||||
|
EXECUTE subquery_prepare_param_non_partkey(1);
|
||||||
|
DEBUG: push down of limit count: 5
|
||||||
|
DEBUG: generating subplan 22_1 for subquery SELECT DISTINCT ROW(users_table.user_id, events_table.event_type)::subquery_prepared_statements.xy AS values_of_subquery FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.user_id) AND (events_table.event_type = 1)) ORDER BY ROW(users_table.user_id, events_table.event_type)::subquery_prepared_statements.xy DESC LIMIT 5
|
||||||
|
values_of_subquery
|
||||||
|
--------------------
|
||||||
|
(6,1)
|
||||||
|
(5,1)
|
||||||
|
(4,1)
|
||||||
|
(3,1)
|
||||||
|
(2,1)
|
||||||
|
(5 rows)
|
||||||
|
|
||||||
|
EXECUTE subquery_prepare_param_non_partkey(1);
|
||||||
|
DEBUG: push down of limit count: 5
|
||||||
|
DEBUG: generating subplan 24_1 for subquery SELECT DISTINCT ROW(users_table.user_id, events_table.event_type)::subquery_prepared_statements.xy AS values_of_subquery FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.user_id) AND (events_table.event_type = 1)) ORDER BY ROW(users_table.user_id, events_table.event_type)::subquery_prepared_statements.xy DESC LIMIT 5
|
||||||
|
values_of_subquery
|
||||||
|
--------------------
|
||||||
|
(6,1)
|
||||||
|
(5,1)
|
||||||
|
(4,1)
|
||||||
|
(3,1)
|
||||||
|
(2,1)
|
||||||
|
(5 rows)
|
||||||
|
|
||||||
|
EXECUTE subquery_prepare_param_non_partkey(1);
|
||||||
|
DEBUG: push down of limit count: 5
|
||||||
|
DEBUG: generating subplan 27_1 for subquery SELECT DISTINCT ROW(users_table.user_id, events_table.event_type)::subquery_prepared_statements.xy AS values_of_subquery FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.user_id) AND (events_table.event_type = 1)) ORDER BY ROW(users_table.user_id, events_table.event_type)::subquery_prepared_statements.xy DESC LIMIT 5
|
||||||
|
values_of_subquery
|
||||||
|
--------------------
|
||||||
|
(6,1)
|
||||||
|
(5,1)
|
||||||
|
(4,1)
|
||||||
|
(3,1)
|
||||||
|
(2,1)
|
||||||
|
(5 rows)
|
||||||
|
|
||||||
|
SET client_min_messages TO DEFAULT;
|
||||||
|
DROP SCHEMA subquery_prepared_statements CASCADE;
|
||||||
|
NOTICE: drop cascades to type xy
|
||||||
|
SET search_path TO public;
|
|
@ -0,0 +1,566 @@
|
||||||
|
-- ===================================================================
|
||||||
|
-- test recursive planning functionality on views
|
||||||
|
-- ===================================================================
|
||||||
|
CREATE SCHEMA subquery_view;
|
||||||
|
SET search_path TO subquery_view, public;
|
||||||
|
CREATE TABLE users_table_local AS SELECT * FROM users_table;
|
||||||
|
CREATE TABLE events_table_local AS SELECT * FROM events_table;
|
||||||
|
SET client_min_messages TO DEBUG1;
|
||||||
|
CREATE VIEW view_without_subquery AS
|
||||||
|
SELECT
|
||||||
|
DISTINCT users_table.value_1
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
ORDER BY 1 DESC;
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
view_without_subquery
|
||||||
|
ORDER BY 1 DESC LIMIT 5;
|
||||||
|
DEBUG: generating subplan 3_1 for subquery SELECT DISTINCT users_table.value_1 FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.user_id) AND (events_table.event_type = ANY (ARRAY[1, 2, 3, 4]))) ORDER BY users_table.value_1 DESC
|
||||||
|
value_1
|
||||||
|
---------
|
||||||
|
5
|
||||||
|
4
|
||||||
|
3
|
||||||
|
2
|
||||||
|
1
|
||||||
|
(5 rows)
|
||||||
|
|
||||||
|
CREATE VIEW view_without_subquery_second AS
|
||||||
|
SELECT
|
||||||
|
DISTINCT users_table.user_id
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
ORDER BY 1 DESC
|
||||||
|
LIMIT 5;
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
view_without_subquery_second
|
||||||
|
ORDER BY 1;
|
||||||
|
DEBUG: push down of limit count: 5
|
||||||
|
DEBUG: generating subplan 5_1 for subquery SELECT DISTINCT users_table.user_id FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.user_id) AND (events_table.event_type = ANY (ARRAY[1, 2, 3, 4]))) ORDER BY users_table.user_id DESC LIMIT 5
|
||||||
|
user_id
|
||||||
|
---------
|
||||||
|
2
|
||||||
|
3
|
||||||
|
4
|
||||||
|
5
|
||||||
|
6
|
||||||
|
(5 rows)
|
||||||
|
|
||||||
|
-- subqueries in FROM clause with LIMIT should be recursively planned
|
||||||
|
CREATE VIEW subquery_limit AS
|
||||||
|
SELECT
|
||||||
|
user_id
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
DISTINCT users_table.user_id
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
ORDER BY 1 DESC LIMIT 5
|
||||||
|
) as foo
|
||||||
|
ORDER BY 1 DESC;
|
||||||
|
SELECT * FROM subquery_limit ORDER BY 1 DESC;
|
||||||
|
DEBUG: push down of limit count: 5
|
||||||
|
DEBUG: generating subplan 7_1 for subquery SELECT DISTINCT users_table.user_id FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.user_id) AND (events_table.event_type = ANY (ARRAY[1, 2, 3, 4]))) ORDER BY users_table.user_id DESC LIMIT 5
|
||||||
|
user_id
|
||||||
|
---------
|
||||||
|
6
|
||||||
|
5
|
||||||
|
4
|
||||||
|
3
|
||||||
|
2
|
||||||
|
(5 rows)
|
||||||
|
|
||||||
|
-- subqueries in FROM clause with GROUP BY non-distribution column should be recursively planned
|
||||||
|
CREATE VIEW subquery_non_p_key_group_by AS
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
DISTINCT users_table.value_1
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
ORDER BY 1
|
||||||
|
) as foo
|
||||||
|
ORDER BY 1 DESC;
|
||||||
|
SELECT * FROM subquery_non_p_key_group_by ORDER BY 1 DESC;
|
||||||
|
DEBUG: generating subplan 9_1 for subquery SELECT DISTINCT users_table.value_1 FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.user_id) AND (events_table.event_type = ANY (ARRAY[1, 2, 3, 4]))) ORDER BY users_table.value_1
|
||||||
|
value_1
|
||||||
|
---------
|
||||||
|
5
|
||||||
|
4
|
||||||
|
3
|
||||||
|
2
|
||||||
|
1
|
||||||
|
0
|
||||||
|
(6 rows)
|
||||||
|
|
||||||
|
CREATE VIEW final_query_router AS
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
users_table.value_2
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
GROUP BY users_table.value_2
|
||||||
|
ORDER BY 1 DESC
|
||||||
|
) as foo,
|
||||||
|
(SELECT
|
||||||
|
users_table.value_3
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (5,6,7,8)
|
||||||
|
GROUP BY users_table.value_3
|
||||||
|
ORDER BY 1 DESC
|
||||||
|
) as bar
|
||||||
|
WHERE foo.value_2 = bar.value_3
|
||||||
|
ORDER BY 2 DESC, 1;
|
||||||
|
SELECT * FROM final_query_router ORDER BY 1;
|
||||||
|
DEBUG: generating subplan 11_1 for subquery SELECT users_table.value_2 FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.user_id) AND (events_table.event_type = ANY (ARRAY[1, 2, 3, 4]))) GROUP BY users_table.value_2 ORDER BY users_table.value_2 DESC
|
||||||
|
DEBUG: generating subplan 11_2 for subquery SELECT users_table.value_3 FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.user_id) AND (events_table.event_type = ANY (ARRAY[5, 6, 7, 8]))) GROUP BY users_table.value_3 ORDER BY users_table.value_3 DESC
|
||||||
|
value_2 | value_3
|
||||||
|
---------+---------
|
||||||
|
0 | 0
|
||||||
|
1 | 1
|
||||||
|
2 | 2
|
||||||
|
3 | 3
|
||||||
|
4 | 4
|
||||||
|
5 | 5
|
||||||
|
(6 rows)
|
||||||
|
|
||||||
|
CREATE VIEW final_query_realtime AS
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
users_table.value_2
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
GROUP BY users_table.value_2
|
||||||
|
ORDER BY 1 DESC
|
||||||
|
) as foo,
|
||||||
|
(SELECT
|
||||||
|
users_table.user_id
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (5,6,7,8)
|
||||||
|
ORDER BY 1 DESC
|
||||||
|
) as bar
|
||||||
|
WHERE foo.value_2 = bar.user_id
|
||||||
|
ORDER BY 2 DESC, 1 DESC
|
||||||
|
LIMIT 3;
|
||||||
|
SELECT
|
||||||
|
DISTINCT ON (users_table.value_2) users_table.value_2, time, value_3
|
||||||
|
FROM
|
||||||
|
final_query_realtime, users_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = final_query_realtime.user_id
|
||||||
|
ORDER BY 1 DESC, 2 DESC, 3 DESC
|
||||||
|
LIMIT 3;
|
||||||
|
DEBUG: generating subplan 14_1 for subquery SELECT users_table.value_2 FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.user_id) AND (events_table.event_type = ANY (ARRAY[1, 2, 3, 4]))) GROUP BY users_table.value_2 ORDER BY users_table.value_2 DESC
|
||||||
|
DEBUG: push down of limit count: 3
|
||||||
|
DEBUG: generating subplan 14_2 for subquery SELECT foo.value_2, bar.user_id FROM (SELECT intermediate_result.value_2 FROM read_intermediate_result('14_1'::text, 'binary'::citus_copy_format) intermediate_result(value_2 integer)) foo, (SELECT users_table.user_id FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.user_id) AND (events_table.event_type = ANY (ARRAY[5, 6, 7, 8]))) ORDER BY users_table.user_id DESC) bar WHERE (foo.value_2 = bar.user_id) ORDER BY bar.user_id DESC, foo.value_2 DESC LIMIT 3
|
||||||
|
DEBUG: push down of limit count: 3
|
||||||
|
value_2 | time | value_3
|
||||||
|
---------+---------------------------------+---------
|
||||||
|
5 | Thu Nov 23 16:28:38.455322 2017 | 4
|
||||||
|
4 | Thu Nov 23 10:22:39.468816 2017 | 3
|
||||||
|
3 | Thu Nov 23 15:55:08.493462 2017 | 3
|
||||||
|
(3 rows)
|
||||||
|
|
||||||
|
CREATE VIEW subquery_in_where AS
|
||||||
|
SELECT DISTINCT user_id
|
||||||
|
FROM users_table
|
||||||
|
WHERE
|
||||||
|
user_id IN (SELECT DISTINCT value_2 FROM users_table WHERE value_1 >= 1 AND value_1 <= 20 ORDER BY 1 LIMIT 5);
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
subquery_in_where
|
||||||
|
ORDER BY 1 DESC;
|
||||||
|
DEBUG: push down of limit count: 5
|
||||||
|
DEBUG: generating subplan 17_1 for subquery SELECT DISTINCT value_2 FROM public.users_table WHERE ((value_1 >= 1) AND (value_1 <= 20)) ORDER BY value_2 LIMIT 5
|
||||||
|
user_id
|
||||||
|
---------
|
||||||
|
4
|
||||||
|
3
|
||||||
|
2
|
||||||
|
1
|
||||||
|
(4 rows)
|
||||||
|
|
||||||
|
-- subquery in FROM -> FROM -> WHERE should be replaced due to LIMIT
|
||||||
|
CREATE VIEW subquery_from_from_where AS
|
||||||
|
SELECT user_id, array_length(events_table, 1)
|
||||||
|
FROM (
|
||||||
|
SELECT user_id, array_agg(event ORDER BY time) AS events_table
|
||||||
|
FROM (
|
||||||
|
SELECT
|
||||||
|
u.user_id, e.event_type::text AS event, e.time
|
||||||
|
FROM
|
||||||
|
users_table AS u,
|
||||||
|
events_table AS e
|
||||||
|
WHERE u.user_id = e.user_id AND
|
||||||
|
u.user_id IN
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
user_id
|
||||||
|
FROM
|
||||||
|
users_table
|
||||||
|
WHERE value_2 >= 5
|
||||||
|
AND EXISTS (SELECT user_id FROM events_table WHERE event_type > 1 AND event_type <= 3 AND value_3 > 1 AND user_id = users_table.user_id)
|
||||||
|
AND NOT EXISTS (SELECT user_id FROM events_table WHERE event_type > 3 AND event_type <= 4 AND value_3 > 1 AND user_id = users_table.user_id)
|
||||||
|
LIMIT 5
|
||||||
|
)
|
||||||
|
) t
|
||||||
|
GROUP BY user_id
|
||||||
|
) q;
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
subquery_from_from_where
|
||||||
|
ORDER BY
|
||||||
|
2 DESC, 1;
|
||||||
|
DEBUG: push down of limit count: 5
|
||||||
|
DEBUG: generating subplan 19_1 for subquery SELECT user_id FROM public.users_table WHERE ((value_2 >= 5) AND (EXISTS (SELECT events_table.user_id FROM public.events_table WHERE ((events_table.event_type > 1) AND (events_table.event_type <= 3) AND (events_table.value_3 > (1)::double precision) AND (events_table.user_id = users_table.user_id)))) AND (NOT (EXISTS (SELECT events_table.user_id FROM public.events_table WHERE ((events_table.event_type > 3) AND (events_table.event_type <= 4) AND (events_table.value_3 > (1)::double precision) AND (events_table.user_id = users_table.user_id)))))) LIMIT 5
|
||||||
|
user_id | array_length
|
||||||
|
---------+--------------
|
||||||
|
5 | 364
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- subquery in FROM -> FROM -> FROM should be replaced if
|
||||||
|
-- it contains onle local tables
|
||||||
|
CREATE VIEW subquery_from_from_where_local_table AS
|
||||||
|
SELECT
|
||||||
|
DISTINCT user_id
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT users_table.user_id FROM users_table,
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
event_type, user_id
|
||||||
|
FROM
|
||||||
|
(SELECT event_type, users_table.user_id FROM users_table,
|
||||||
|
(SELECT user_id, event_type FROM events_table_local WHERE value_2 < 3 OFFSET 3) as foo
|
||||||
|
WHERE foo.user_id = users_table.user_id
|
||||||
|
) bar
|
||||||
|
) as baz
|
||||||
|
WHERE baz.user_id = users_table.user_id
|
||||||
|
) as sub1;
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
subquery_from_from_where
|
||||||
|
ORDER BY 1 DESC
|
||||||
|
LIMIT 3;
|
||||||
|
DEBUG: push down of limit count: 5
|
||||||
|
DEBUG: generating subplan 21_1 for subquery SELECT user_id FROM public.users_table WHERE ((value_2 >= 5) AND (EXISTS (SELECT events_table.user_id FROM public.events_table WHERE ((events_table.event_type > 1) AND (events_table.event_type <= 3) AND (events_table.value_3 > (1)::double precision) AND (events_table.user_id = users_table.user_id)))) AND (NOT (EXISTS (SELECT events_table.user_id FROM public.events_table WHERE ((events_table.event_type > 3) AND (events_table.event_type <= 4) AND (events_table.value_3 > (1)::double precision) AND (events_table.user_id = users_table.user_id)))))) LIMIT 5
|
||||||
|
DEBUG: push down of limit count: 3
|
||||||
|
user_id | array_length
|
||||||
|
---------+--------------
|
||||||
|
5 | 364
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SET citus.enable_repartition_joins to ON;
|
||||||
|
CREATE VIEW repartition_view AS
|
||||||
|
SELECT
|
||||||
|
count(*)
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT DISTINCT users_table.value_2 FROM users_table, events_table WHERE users_table.user_id = events_table.value_2 AND users_table.user_id < 2
|
||||||
|
) as foo,
|
||||||
|
(
|
||||||
|
SELECT user_id FROM users_table
|
||||||
|
) as bar
|
||||||
|
WHERE foo.value_2 = bar.user_id;
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
repartition_view;
|
||||||
|
DEBUG: cannot use real time executor with repartition jobs
|
||||||
|
HINT: Since you enabled citus.enable_repartition_joins Citus chose to use task-tracker.
|
||||||
|
DEBUG: generating subplan 23_1 for subquery SELECT DISTINCT users_table.value_2 FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.value_2) AND (users_table.user_id < 2))
|
||||||
|
DEBUG: generating subplan 23_2 for subquery SELECT count(*) AS count FROM (SELECT intermediate_result.value_2 FROM read_intermediate_result('23_1'::text, 'binary'::citus_copy_format) intermediate_result(value_2 integer)) foo, (SELECT users_table.user_id FROM public.users_table) bar WHERE (foo.value_2 = bar.user_id)
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
58
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
CREATE VIEW all_executors_view AS
|
||||||
|
SELECT
|
||||||
|
count(*)
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT value_2 FROM users_table WHERE user_id = 15 OFFSET 0
|
||||||
|
) as foo,
|
||||||
|
(
|
||||||
|
SELECT user_id FROM users_table OFFSET 0
|
||||||
|
) as bar,
|
||||||
|
(
|
||||||
|
SELECT DISTINCT users_table.value_2 FROM users_table, events_table WHERE users_table.user_id = events_table.value_2 AND users_table.user_id < 2
|
||||||
|
) baz,
|
||||||
|
(
|
||||||
|
SELECT user_id FROM users_table_local WHERE user_id = 2
|
||||||
|
) baw
|
||||||
|
WHERE foo.value_2 = bar.user_id AND baz.value_2 = bar.user_id AND bar.user_id = baw.user_id;
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
all_executors_view;
|
||||||
|
DEBUG: generating subplan 26_1 for subquery SELECT value_2 FROM public.users_table WHERE (user_id = 15) OFFSET 0
|
||||||
|
DEBUG: generating subplan 26_2 for subquery SELECT user_id FROM public.users_table OFFSET 0
|
||||||
|
DEBUG: cannot use real time executor with repartition jobs
|
||||||
|
HINT: Since you enabled citus.enable_repartition_joins Citus chose to use task-tracker.
|
||||||
|
DEBUG: generating subplan 26_3 for subquery SELECT DISTINCT users_table.value_2 FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.value_2) AND (users_table.user_id < 2))
|
||||||
|
DEBUG: generating subplan 26_4 for subquery SELECT user_id FROM subquery_view.users_table_local WHERE (user_id = 2)
|
||||||
|
DEBUG: generating subplan 26_5 for subquery SELECT count(*) AS count FROM (SELECT intermediate_result.value_2 FROM read_intermediate_result('26_1'::text, 'binary'::citus_copy_format) intermediate_result(value_2 integer)) foo, (SELECT intermediate_result.user_id FROM read_intermediate_result('26_2'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) bar, (SELECT intermediate_result.value_2 FROM read_intermediate_result('26_3'::text, 'binary'::citus_copy_format) intermediate_result(value_2 integer)) baz, (SELECT intermediate_result.user_id FROM read_intermediate_result('26_4'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) baw WHERE ((foo.value_2 = bar.user_id) AND (baz.value_2 = bar.user_id) AND (bar.user_id = baw.user_id))
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
0
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SET citus.enable_repartition_joins to OFF;
|
||||||
|
-- the same query, but this time the CTEs also live inside a subquery
|
||||||
|
CREATE VIEW subquery_and_ctes AS
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
WITH cte AS (
|
||||||
|
WITH local_cte AS (
|
||||||
|
SELECT * FROM users_table_local
|
||||||
|
),
|
||||||
|
dist_cte AS (
|
||||||
|
SELECT
|
||||||
|
user_id
|
||||||
|
FROM
|
||||||
|
events_table,
|
||||||
|
(SELECT DISTINCT value_2 FROM users_table OFFSET 0) as foo
|
||||||
|
WHERE
|
||||||
|
events_table.user_id = foo.value_2 AND
|
||||||
|
events_table.user_id IN (SELECT DISTINCT value_1 FROM users_table ORDER BY 1 LIMIT 3)
|
||||||
|
)
|
||||||
|
SELECT dist_cte.user_id FROM local_cte join dist_cte on dist_cte.user_id=local_cte.user_id
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
count(*) as cnt
|
||||||
|
FROM
|
||||||
|
cte,
|
||||||
|
(SELECT
|
||||||
|
DISTINCT users_table.user_id
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
ORDER BY 1 DESC LIMIT 5
|
||||||
|
) as foo
|
||||||
|
WHERE foo.user_id = cte.user_id
|
||||||
|
) as foo, users_table WHERE foo.cnt > users_table.value_2;
|
||||||
|
SELECT * FROM subquery_and_ctes
|
||||||
|
ORDER BY 3 DESC, 1 DESC, 2 DESC, 4 DESC
|
||||||
|
LIMIT 5;
|
||||||
|
DEBUG: generating subplan 31_1 for CTE cte: WITH local_cte AS (SELECT users_table_local.user_id, users_table_local."time", users_table_local.value_1, users_table_local.value_2, users_table_local.value_3, users_table_local.value_4 FROM subquery_view.users_table_local), dist_cte AS (SELECT events_table.user_id FROM public.events_table, (SELECT DISTINCT users_table.value_2 FROM public.users_table OFFSET 0) foo WHERE ((events_table.user_id = foo.value_2) AND (events_table.user_id IN (SELECT DISTINCT users_table.value_1 FROM public.users_table ORDER BY users_table.value_1 LIMIT 3)))) SELECT dist_cte.user_id FROM (local_cte JOIN dist_cte ON ((dist_cte.user_id = local_cte.user_id)))
|
||||||
|
DEBUG: generating subplan 32_1 for CTE local_cte: SELECT user_id, "time", value_1, value_2, value_3, value_4 FROM subquery_view.users_table_local
|
||||||
|
DEBUG: generating subplan 32_2 for CTE dist_cte: SELECT events_table.user_id FROM public.events_table, (SELECT DISTINCT users_table.value_2 FROM public.users_table OFFSET 0) foo WHERE ((events_table.user_id = foo.value_2) AND (events_table.user_id IN (SELECT DISTINCT users_table.value_1 FROM public.users_table ORDER BY users_table.value_1 LIMIT 3)))
|
||||||
|
DEBUG: push down of limit count: 3
|
||||||
|
DEBUG: generating subplan 33_1 for subquery SELECT DISTINCT value_1 FROM public.users_table ORDER BY value_1 LIMIT 3
|
||||||
|
DEBUG: generating subplan 33_2 for subquery SELECT DISTINCT value_2 FROM public.users_table OFFSET 0
|
||||||
|
DEBUG: push down of limit count: 5
|
||||||
|
DEBUG: generating subplan 31_2 for subquery SELECT DISTINCT users_table.user_id FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.user_id) AND (events_table.event_type = ANY (ARRAY[1, 2, 3, 4]))) ORDER BY users_table.user_id DESC LIMIT 5
|
||||||
|
DEBUG: generating subplan 31_3 for subquery SELECT count(*) AS cnt FROM (SELECT intermediate_result.user_id FROM read_intermediate_result('31_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) cte, (SELECT intermediate_result.user_id FROM read_intermediate_result('31_2'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) foo WHERE (foo.user_id = cte.user_id)
|
||||||
|
DEBUG: push down of limit count: 5
|
||||||
|
cnt | user_id | time | value_1 | value_2 | value_3 | value_4
|
||||||
|
-----+---------+---------------------------------+---------+---------+---------+---------
|
||||||
|
432 | 1 | Thu Nov 23 17:30:34.635085 2017 | 3 | 4 | 4 |
|
||||||
|
432 | 1 | Thu Nov 23 17:23:03.441394 2017 | 5 | 4 | 3 |
|
||||||
|
432 | 3 | Thu Nov 23 17:18:51.048758 2017 | 1 | 5 | 5 |
|
||||||
|
432 | 3 | Thu Nov 23 17:10:35.959913 2017 | 4 | 3 | 1 |
|
||||||
|
432 | 5 | Thu Nov 23 16:48:32.08896 2017 | 5 | 2 | 1 |
|
||||||
|
(5 rows)
|
||||||
|
|
||||||
|
CREATE VIEW subquery_and_ctes_second AS
|
||||||
|
SELECT time, event_type, value_2, value_3 FROM
|
||||||
|
(
|
||||||
|
WITH cte AS (
|
||||||
|
WITH local_cte AS (
|
||||||
|
SELECT * FROM users_table_local
|
||||||
|
),
|
||||||
|
dist_cte AS (
|
||||||
|
SELECT user_id FROM events_table
|
||||||
|
)
|
||||||
|
SELECT dist_cte.user_id FROM local_cte join dist_cte on dist_cte.user_id=local_cte.user_id
|
||||||
|
)
|
||||||
|
SELECT DISTINCT cte.user_id
|
||||||
|
FROM users_table, cte
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = cte.user_id AND
|
||||||
|
users_table.user_id IN
|
||||||
|
(WITH cte_in_where AS (SELECT DISTINCT value_2 FROM users_table WHERE value_1 >= 1 AND value_1 <= 20 ORDER BY 1 LIMIT 5) SELECT * FROM cte_in_where)
|
||||||
|
ORDER BY 1 DESC
|
||||||
|
) as foo,
|
||||||
|
events_table
|
||||||
|
WHERE
|
||||||
|
foo.user_id = events_table.value_2;
|
||||||
|
SELECT * FROM subquery_and_ctes_second
|
||||||
|
ORDER BY 3 DESC, 2 DESC, 1 DESC
|
||||||
|
LIMIT 5;
|
||||||
|
DEBUG: generating subplan 38_1 for CTE cte: WITH local_cte AS (SELECT users_table_local.user_id, users_table_local."time", users_table_local.value_1, users_table_local.value_2, users_table_local.value_3, users_table_local.value_4 FROM subquery_view.users_table_local), dist_cte AS (SELECT events_table.user_id FROM public.events_table) SELECT dist_cte.user_id FROM (local_cte JOIN dist_cte ON ((dist_cte.user_id = local_cte.user_id)))
|
||||||
|
DEBUG: generating subplan 39_1 for CTE local_cte: SELECT user_id, "time", value_1, value_2, value_3, value_4 FROM subquery_view.users_table_local
|
||||||
|
DEBUG: generating subplan 39_2 for CTE dist_cte: SELECT user_id FROM public.events_table
|
||||||
|
DEBUG: generating subplan 38_2 for CTE cte_in_where: SELECT DISTINCT value_2 FROM public.users_table WHERE ((value_1 >= 1) AND (value_1 <= 20)) ORDER BY value_2 LIMIT 5
|
||||||
|
DEBUG: push down of limit count: 5
|
||||||
|
DEBUG: generating subplan 38_3 for subquery SELECT DISTINCT cte.user_id FROM public.users_table, (SELECT intermediate_result.user_id FROM read_intermediate_result('38_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) cte WHERE ((users_table.user_id = cte.user_id) AND (users_table.user_id IN (SELECT cte_in_where.value_2 FROM (SELECT intermediate_result.value_2 FROM read_intermediate_result('38_2'::text, 'binary'::citus_copy_format) intermediate_result(value_2 integer)) cte_in_where))) ORDER BY cte.user_id DESC
|
||||||
|
DEBUG: push down of limit count: 5
|
||||||
|
time | event_type | value_2 | value_3
|
||||||
|
---------------------------------+------------+---------+---------
|
||||||
|
Thu Nov 23 21:54:46.924477 2017 | 6 | 4 | 5
|
||||||
|
Wed Nov 22 21:24:22.849224 2017 | 5 | 4 | 1
|
||||||
|
Wed Nov 22 21:05:25.194441 2017 | 5 | 4 | 1
|
||||||
|
Thu Nov 23 04:01:12.29256 2017 | 4 | 4 | 3
|
||||||
|
Thu Nov 23 09:33:16.992454 2017 | 3 | 4 | 1
|
||||||
|
(5 rows)
|
||||||
|
|
||||||
|
CREATE VIEW deep_subquery AS
|
||||||
|
SELECT count(*)
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT avg(min) FROM
|
||||||
|
(
|
||||||
|
SELECT min(users_table.value_1) FROM
|
||||||
|
(
|
||||||
|
SELECT avg(event_type) as avg_ev_type FROM
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
max(value_1) as mx_val_1
|
||||||
|
FROM (
|
||||||
|
SELECT
|
||||||
|
avg(event_type) as avg
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
cnt
|
||||||
|
FROM
|
||||||
|
(SELECT count(*) as cnt, value_2 FROM users_table GROUP BY value_2) as level_1, users_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = level_1.cnt
|
||||||
|
) as level_2, events_table
|
||||||
|
WHERE events_table.user_id = level_2.cnt
|
||||||
|
GROUP BY level_2.cnt
|
||||||
|
) as level_3, users_table
|
||||||
|
WHERE user_id = level_3.avg
|
||||||
|
GROUP BY level_3.avg
|
||||||
|
) as level_4, events_table
|
||||||
|
WHERE level_4.mx_val_1 = events_table.user_id
|
||||||
|
GROUP BY level_4.mx_val_1
|
||||||
|
) as level_5, users_table
|
||||||
|
WHERE
|
||||||
|
level_5.avg_ev_type = users_table.user_id
|
||||||
|
GROUP BY
|
||||||
|
level_5.avg_ev_type
|
||||||
|
) as level_6, users_table WHERE users_table.user_id = level_6.min
|
||||||
|
GROUP BY users_table.value_1
|
||||||
|
) as bar;
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
deep_subquery;
|
||||||
|
DEBUG: generating subplan 43_1 for subquery SELECT count(*) AS cnt, value_2 FROM public.users_table GROUP BY value_2
|
||||||
|
DEBUG: generating subplan 43_2 for subquery SELECT avg(events_table.event_type) AS avg FROM (SELECT level_1.cnt FROM (SELECT intermediate_result.cnt, intermediate_result.value_2 FROM read_intermediate_result('43_1'::text, 'binary'::citus_copy_format) intermediate_result(cnt bigint, value_2 integer)) level_1, public.users_table WHERE (users_table.user_id = level_1.cnt)) level_2, public.events_table WHERE (events_table.user_id = level_2.cnt) GROUP BY level_2.cnt
|
||||||
|
DEBUG: generating subplan 43_3 for subquery SELECT max(users_table.value_1) AS mx_val_1 FROM (SELECT intermediate_result.avg FROM read_intermediate_result('43_2'::text, 'binary'::citus_copy_format) intermediate_result(avg numeric)) level_3, public.users_table WHERE ((users_table.user_id)::numeric = level_3.avg) GROUP BY level_3.avg
|
||||||
|
DEBUG: generating subplan 43_4 for subquery SELECT avg(events_table.event_type) AS avg_ev_type FROM (SELECT intermediate_result.mx_val_1 FROM read_intermediate_result('43_3'::text, 'binary'::citus_copy_format) intermediate_result(mx_val_1 integer)) level_4, public.events_table WHERE (level_4.mx_val_1 = events_table.user_id) GROUP BY level_4.mx_val_1
|
||||||
|
DEBUG: generating subplan 43_5 for subquery SELECT min(users_table.value_1) AS min FROM (SELECT intermediate_result.avg_ev_type FROM read_intermediate_result('43_4'::text, 'binary'::citus_copy_format) intermediate_result(avg_ev_type numeric)) level_5, public.users_table WHERE (level_5.avg_ev_type = (users_table.user_id)::numeric) GROUP BY level_5.avg_ev_type
|
||||||
|
DEBUG: generating subplan 43_6 for subquery SELECT avg(level_6.min) AS avg FROM (SELECT intermediate_result.min FROM read_intermediate_result('43_5'::text, 'binary'::citus_copy_format) intermediate_result(min integer)) level_6, public.users_table WHERE (users_table.user_id = level_6.min) GROUP BY users_table.value_1
|
||||||
|
DEBUG: generating subplan 43_7 for subquery SELECT count(*) AS count FROM (SELECT intermediate_result.avg FROM read_intermediate_result('43_6'::text, 'binary'::citus_copy_format) intermediate_result(avg numeric)) bar
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
0
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
CREATE VIEW result_of_view_is_also_recursively_planned AS
|
||||||
|
SELECT
|
||||||
|
user_id
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
DISTINCT users_table.user_id
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
ORDER BY 1 DESC LIMIT 5
|
||||||
|
) as foo
|
||||||
|
ORDER BY 1 DESC;
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
result_of_view_is_also_recursively_planned, events_table
|
||||||
|
WHERE
|
||||||
|
events_table.value_2 = result_of_view_is_also_recursively_planned.user_id
|
||||||
|
ORDER BY time DESC
|
||||||
|
LIMIT 5
|
||||||
|
OFFSET 4
|
||||||
|
) as foo
|
||||||
|
ORDER BY time DESC LIMIT 5;
|
||||||
|
DEBUG: push down of limit count: 5
|
||||||
|
DEBUG: generating subplan 51_1 for subquery SELECT DISTINCT users_table.user_id FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.user_id) AND (events_table.event_type = ANY (ARRAY[1, 2, 3, 4]))) ORDER BY users_table.user_id DESC LIMIT 5
|
||||||
|
DEBUG: push down of limit count: 9
|
||||||
|
DEBUG: generating subplan 51_2 for subquery SELECT result_of_view_is_also_recursively_planned.user_id, events_table.user_id, events_table."time", events_table.event_type, events_table.value_2, events_table.value_3, events_table.value_4 FROM (SELECT foo.user_id FROM (SELECT intermediate_result.user_id FROM read_intermediate_result('51_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) foo ORDER BY foo.user_id DESC) result_of_view_is_also_recursively_planned, public.events_table WHERE (events_table.value_2 = result_of_view_is_also_recursively_planned.user_id) ORDER BY events_table."time" DESC OFFSET 4 LIMIT 5
|
||||||
|
user_id | user_id | time | event_type | value_2 | value_3 | value_4
|
||||||
|
---------+---------+---------------------------------+------------+---------+---------+---------
|
||||||
|
2 | 3 | Thu Nov 23 16:44:41.903713 2017 | 4 | 2 | 2 |
|
||||||
|
2 | 5 | Thu Nov 23 16:11:02.929469 2017 | 4 | 2 | 0 |
|
||||||
|
4 | 5 | Thu Nov 23 14:40:40.467511 2017 | 1 | 4 | 1 |
|
||||||
|
3 | 2 | Thu Nov 23 14:02:47.738901 2017 | 1 | 3 | 2 |
|
||||||
|
3 | 6 | Thu Nov 23 14:00:13.20013 2017 | 3 | 3 | 3 |
|
||||||
|
(5 rows)
|
||||||
|
|
||||||
|
SET client_min_messages TO DEFAULT;
|
||||||
|
DROP SCHEMA subquery_view CASCADE;
|
||||||
|
NOTICE: drop cascades to 17 other objects
|
||||||
|
DETAIL: drop cascades to table users_table_local
|
||||||
|
drop cascades to table events_table_local
|
||||||
|
drop cascades to view view_without_subquery
|
||||||
|
drop cascades to view view_without_subquery_second
|
||||||
|
drop cascades to view subquery_limit
|
||||||
|
drop cascades to view subquery_non_p_key_group_by
|
||||||
|
drop cascades to view final_query_router
|
||||||
|
drop cascades to view final_query_realtime
|
||||||
|
drop cascades to view subquery_in_where
|
||||||
|
drop cascades to view subquery_from_from_where
|
||||||
|
drop cascades to view subquery_from_from_where_local_table
|
||||||
|
drop cascades to view repartition_view
|
||||||
|
drop cascades to view all_executors_view
|
||||||
|
drop cascades to view subquery_and_ctes
|
||||||
|
drop cascades to view subquery_and_ctes_second
|
||||||
|
drop cascades to view deep_subquery
|
||||||
|
drop cascades to view result_of_view_is_also_recursively_planned
|
||||||
|
SET search_path TO public;
|
|
@ -86,22 +86,27 @@ LIMIT
|
||||||
6 | 5
|
6 | 5
|
||||||
(5 rows)
|
(5 rows)
|
||||||
|
|
||||||
-- CTE in subquery errors out
|
-- CTE in subquery recursively planned
|
||||||
SELECT user_id FROM (
|
SELECT user_id FROM (
|
||||||
WITH cte AS (
|
WITH cte AS (
|
||||||
SELECT user_id, value_2 from users_table WHERE user_id IN (1, 2) ORDER BY 2 LIMIT 5
|
SELECT user_id, value_2 from users_table WHERE user_id IN (1, 2) ORDER BY 2 LIMIT 5
|
||||||
)
|
)
|
||||||
SELECT user_id FROM cte WHERE value_2 > 0
|
SELECT user_id FROM cte WHERE value_2 > 0
|
||||||
) a;
|
) a ORDER BY 1 LIMIT 3;
|
||||||
ERROR: cannot push down this subquery
|
user_id
|
||||||
DETAIL: CTEs in subqueries are currently unsupported
|
---------
|
||||||
|
2
|
||||||
|
2
|
||||||
|
2
|
||||||
|
(3 rows)
|
||||||
|
|
||||||
-- CTE outside of FROM/WHERE errors out
|
-- CTE outside of FROM/WHERE errors out
|
||||||
WITH cte AS (
|
WITH cte AS (
|
||||||
SELECT user_id FROM users_table WHERE value_2 IN (1, 2)
|
SELECT user_id FROM users_table WHERE value_2 IN (1, 2)
|
||||||
)
|
)
|
||||||
SELECT (SELECT * FROM cte);
|
SELECT (SELECT * FROM cte);
|
||||||
WARNING: more than one row returned by a subquery used as an expression
|
WARNING: more than one row returned by a subquery used as an expression
|
||||||
CONTEXT: while executing command on localhost:57638
|
CONTEXT: while executing command on localhost:57637
|
||||||
ERROR: could not receive query results
|
ERROR: could not receive query results
|
||||||
WITH cte_basic AS (
|
WITH cte_basic AS (
|
||||||
SELECT user_id FROM users_table WHERE user_id = 1
|
SELECT user_id FROM users_table WHERE user_id = 1
|
||||||
|
@ -541,8 +546,7 @@ FROM
|
||||||
SELECT * FROM users_table WHERE user_id>1
|
SELECT * FROM users_table WHERE user_id>1
|
||||||
)
|
)
|
||||||
SELECT * FROM basic_recursive ORDER BY user_id LIMIT 1) cte_rec;
|
SELECT * FROM basic_recursive ORDER BY user_id LIMIT 1) cte_rec;
|
||||||
ERROR: cannot push down this subquery
|
ERROR: recursive CTEs are not supported in distributed queries
|
||||||
DETAIL: CTEs in subqueries are currently unsupported
|
|
||||||
-- basic_recursive in WHERE with UNION ALL
|
-- basic_recursive in WHERE with UNION ALL
|
||||||
SELECT
|
SELECT
|
||||||
*
|
*
|
||||||
|
@ -615,15 +619,24 @@ SELECT user_id, sum(value_2) FROM cte_user GROUP BY 1 ORDER BY 1, 2;
|
||||||
6 | 220
|
6 | 220
|
||||||
(6 rows)
|
(6 rows)
|
||||||
|
|
||||||
SELECT * FROM cte_view;
|
SELECT * FROM cte_view ORDER BY 1, 2 LIMIT 5;
|
||||||
ERROR: cannot push down this subquery
|
user_id | value_1
|
||||||
DETAIL: CTEs in subqueries are currently unsupported
|
---------+---------
|
||||||
|
1 | 5
|
||||||
|
2 | 4
|
||||||
|
3 | 5
|
||||||
|
4 | 5
|
||||||
|
5 | 5
|
||||||
|
(5 rows)
|
||||||
|
|
||||||
WITH cte_user_with_view AS
|
WITH cte_user_with_view AS
|
||||||
(
|
(
|
||||||
SELECT * FROM cte_view WHERE user_id < 3
|
SELECT * FROM cte_view WHERE user_id < 3
|
||||||
)
|
)
|
||||||
SELECT user_id, value_1 FROM cte_user_with_view ORDER BY 1, 2 LIMIT 10 OFFSET 3;
|
SELECT user_id, value_1 FROM cte_user_with_view ORDER BY 1, 2 LIMIT 10 OFFSET 2;
|
||||||
ERROR: cannot push down this subquery
|
user_id | value_1
|
||||||
DETAIL: CTEs in subqueries are currently unsupported
|
---------+---------
|
||||||
|
(0 rows)
|
||||||
|
|
||||||
DROP VIEW basic_view;
|
DROP VIEW basic_view;
|
||||||
DROP VIEW cte_view;
|
DROP VIEW cte_view;
|
||||||
|
|
|
@ -84,6 +84,7 @@ ORDER BY
|
||||||
|
|
||||||
-- Subqueries in WHERE and FROM are mixed
|
-- Subqueries in WHERE and FROM are mixed
|
||||||
-- In this query, only subquery in WHERE is not a colocated join
|
-- In this query, only subquery in WHERE is not a colocated join
|
||||||
|
-- but we're able to recursively plan that as well
|
||||||
WITH users_events AS (
|
WITH users_events AS (
|
||||||
WITH colocated_join AS (
|
WITH colocated_join AS (
|
||||||
SELECT
|
SELECT
|
||||||
|
@ -135,15 +136,22 @@ WITH users_events AS (
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
SELECT
|
SELECT
|
||||||
*
|
DISTINCT uid
|
||||||
FROM
|
FROM
|
||||||
users_events
|
users_events
|
||||||
ORDER BY
|
ORDER BY
|
||||||
1, 2
|
1 DESC
|
||||||
LIMIT
|
LIMIT
|
||||||
20;
|
5;
|
||||||
ERROR: cannot pushdown the subquery
|
uid
|
||||||
DETAIL: Complex subqueries and CTEs are not allowed in the FROM clause when the query has subqueries in the WHERE clause
|
-----
|
||||||
|
6
|
||||||
|
5
|
||||||
|
4
|
||||||
|
3
|
||||||
|
2
|
||||||
|
(5 rows)
|
||||||
|
|
||||||
-- cte LEFT JOIN distributed_table should error out
|
-- cte LEFT JOIN distributed_table should error out
|
||||||
WITH cte AS (
|
WITH cte AS (
|
||||||
SELECT * FROM users_table WHERE user_id = 1 ORDER BY value_1
|
SELECT * FROM users_table WHERE user_id = 1 ORDER BY value_1
|
||||||
|
|
|
@ -122,6 +122,10 @@ WHERE
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
-- CTE in WHERE basic
|
-- CTE in WHERE basic
|
||||||
|
-- this is a tricky query that hits an aggresive
|
||||||
|
-- check in subquery puwhdown after the recursive planning
|
||||||
|
-- where LIMIT should be allowed
|
||||||
|
-- if the query contains only intermediate results
|
||||||
SELECT
|
SELECT
|
||||||
count(*)
|
count(*)
|
||||||
FROM
|
FROM
|
||||||
|
@ -147,6 +151,10 @@ IN
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
-- CTE with non-colocated join in WHERE
|
-- CTE with non-colocated join in WHERE
|
||||||
|
-- this is a tricky query that hits an aggresive
|
||||||
|
-- check in subquery puwhdown after the recursive planning
|
||||||
|
-- where LIMIT should be allowed
|
||||||
|
-- if the query contains only intermediate results
|
||||||
SELECT
|
SELECT
|
||||||
count(*)
|
count(*)
|
||||||
FROM
|
FROM
|
||||||
|
|
|
@ -38,6 +38,14 @@ test: multi_behavioral_analytics_basics multi_behavioral_analytics_single_shard_
|
||||||
# ----------
|
# ----------
|
||||||
test: multi_partitioning_utils multi_partitioning
|
test: multi_partitioning_utils multi_partitioning
|
||||||
|
|
||||||
|
|
||||||
|
# ----------
|
||||||
|
# Tests for recursive subquery planning
|
||||||
|
# ----------
|
||||||
|
test: subquery_basics subquery_local_tables subquery_executors subquery_and_cte
|
||||||
|
test: subqueries_deep subquery_view subquery_partitioning subquery_complex_target_list subqueries_not_supported
|
||||||
|
test: subquery_prepared_statements
|
||||||
|
|
||||||
# ----------
|
# ----------
|
||||||
# Miscellaneous tests to check our query planning behavior
|
# Miscellaneous tests to check our query planning behavior
|
||||||
# ----------
|
# ----------
|
||||||
|
|
|
@ -157,12 +157,11 @@ SELECT count(*) FROM lineitem, orders WHERE l_orderkey + 1 = o_orderkey;
|
||||||
|
|
||||||
-- Check that we can issue limit/offset queries
|
-- Check that we can issue limit/offset queries
|
||||||
|
|
||||||
-- OFFSET in subqueries are not supported
|
-- the subquery is recursively planned since it contains OFFSET, which is not pushdownable
|
||||||
-- Error in the planner when single repartition subquery
|
SELECT * FROM (SELECT o_custkey FROM orders GROUP BY o_custkey ORDER BY o_custkey OFFSET 20) sq ORDER BY 1 LIMIT 5;
|
||||||
SELECT * FROM (SELECT o_custkey FROM orders GROUP BY o_custkey ORDER BY o_custkey OFFSET 20) sq;
|
|
||||||
|
|
||||||
-- Error in the optimizer when subquery pushdown is on
|
-- the subquery is recursively planned since it contains OFFSET, which is not pushdownable
|
||||||
SELECT * FROM (SELECT o_orderkey FROM orders ORDER BY o_orderkey OFFSET 20) sq;
|
SELECT * FROM (SELECT o_orderkey FROM orders ORDER BY o_orderkey OFFSET 20) sq ORDER BY 1 LIMIT 5;
|
||||||
|
|
||||||
-- Simple LIMIT/OFFSET with ORDER BY
|
-- Simple LIMIT/OFFSET with ORDER BY
|
||||||
SELECT o_orderkey FROM orders ORDER BY o_orderkey LIMIT 10 OFFSET 20;
|
SELECT o_orderkey FROM orders ORDER BY o_orderkey LIMIT 10 OFFSET 20;
|
||||||
|
|
|
@ -795,7 +795,7 @@ FROM (SELECT SUM(raw_events_second.value_4) AS v4,
|
||||||
GROUP BY raw_events_second.user_id) AS foo;
|
GROUP BY raw_events_second.user_id) AS foo;
|
||||||
|
|
||||||
|
|
||||||
-- INSERT partition column does not match with SELECT partition column
|
-- INSERT returns NULL partition key value via coordinator
|
||||||
INSERT INTO agg_events
|
INSERT INTO agg_events
|
||||||
(value_4_agg,
|
(value_4_agg,
|
||||||
value_1_agg,
|
value_1_agg,
|
||||||
|
@ -874,8 +874,7 @@ SELECT
|
||||||
FROM
|
FROM
|
||||||
reference_table;
|
reference_table;
|
||||||
|
|
||||||
-- unsupported joins between subqueries
|
-- foo2 is recursively planned and INSERT...SELECT is done via coordinator
|
||||||
-- we do not return bare partition column on the inner query
|
|
||||||
INSERT INTO agg_events
|
INSERT INTO agg_events
|
||||||
(user_id)
|
(user_id)
|
||||||
SELECT f2.id FROM
|
SELECT f2.id FROM
|
||||||
|
@ -903,6 +902,7 @@ ON (f.id = f2.id);
|
||||||
-- the second part of the query is not routable since
|
-- the second part of the query is not routable since
|
||||||
-- GROUP BY not on the partition column (i.e., value_1) and thus join
|
-- GROUP BY not on the partition column (i.e., value_1) and thus join
|
||||||
-- on f.id = f2.id is not on the partition key (instead on the sum of partition key)
|
-- on f.id = f2.id is not on the partition key (instead on the sum of partition key)
|
||||||
|
-- but we still recursively plan foo2 and run the query
|
||||||
INSERT INTO agg_events
|
INSERT INTO agg_events
|
||||||
(user_id)
|
(user_id)
|
||||||
SELECT f.id FROM
|
SELECT f.id FROM
|
||||||
|
@ -1315,8 +1315,8 @@ SET client_min_messages TO INFO;
|
||||||
-- avoid constraint violations
|
-- avoid constraint violations
|
||||||
TRUNCATE raw_events_first;
|
TRUNCATE raw_events_first;
|
||||||
|
|
||||||
-- we don't support LIMIT even if it exists in the subqueries
|
-- we don't support LIMIT for subquery pushdown, but
|
||||||
-- in where clause
|
-- we recursively plan the query and run it via coordinator
|
||||||
INSERT INTO agg_events(user_id)
|
INSERT INTO agg_events(user_id)
|
||||||
SELECT user_id
|
SELECT user_id
|
||||||
FROM users_table
|
FROM users_table
|
||||||
|
|
|
@ -662,7 +662,7 @@ FROM
|
||||||
ON users_table.user_id = temp.user_id
|
ON users_table.user_id = temp.user_id
|
||||||
WHERE users_table.value_1 < 50;
|
WHERE users_table.value_1 < 50;
|
||||||
|
|
||||||
-- not supported since one of the queries doesn't have a relation
|
-- supported via recursive planning
|
||||||
INSERT INTO agg_results (user_id, agg_time, value_2_agg)
|
INSERT INTO agg_results (user_id, agg_time, value_2_agg)
|
||||||
SELECT
|
SELECT
|
||||||
user_id,
|
user_id,
|
||||||
|
|
|
@ -33,6 +33,24 @@ SELECT a FROM dest_table WHERE a = 1;
|
||||||
-- real-time selects are also allowed
|
-- real-time selects are also allowed
|
||||||
SELECT a FROM dest_table;
|
SELECT a FROM dest_table;
|
||||||
|
|
||||||
|
-- subqueries are also allowed
|
||||||
|
SET client_min_messages TO DEBUG1;
|
||||||
|
SELECT
|
||||||
|
foo.a
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
WITH cte AS (
|
||||||
|
SELECT
|
||||||
|
DISTINCT dest_table.a
|
||||||
|
FROM
|
||||||
|
dest_table, source_table
|
||||||
|
WHERE
|
||||||
|
source_table.a = dest_table.a AND
|
||||||
|
dest_table.b IN (1,2,3,4)
|
||||||
|
) SELECT * FROM cte ORDER BY 1 DESC LIMIT 5
|
||||||
|
) as foo;
|
||||||
|
SET client_min_messages TO DEFAULT;
|
||||||
|
|
||||||
-- insert into is definitely not allowed
|
-- insert into is definitely not allowed
|
||||||
INSERT INTO dest_table (a, b)
|
INSERT INTO dest_table (a, b)
|
||||||
SELECT a, b FROM source_table;
|
SELECT a, b FROM source_table;
|
||||||
|
|
|
@ -127,7 +127,7 @@ SELECT title FROM articles ORDER BY 1 LIMIT 5;
|
||||||
-- queries which involve functions in FROM clause are recursively planned
|
-- queries which involve functions in FROM clause are recursively planned
|
||||||
SELECT * FROM articles, position('om' in 'Thomas') ORDER BY 2 DESC, 1 DESC, 3 DESC LIMIT 5;
|
SELECT * FROM articles, position('om' in 'Thomas') ORDER BY 2 DESC, 1 DESC, 3 DESC LIMIT 5;
|
||||||
|
|
||||||
-- subqueries are not supported in WHERE clause in Citus
|
-- subqueries are supported in WHERE clause in Citus even if the relations are not distributed
|
||||||
SELECT * FROM articles WHERE author_id IN (SELECT id FROM authors WHERE name LIKE '%a');
|
SELECT * FROM articles WHERE author_id IN (SELECT id FROM authors WHERE name LIKE '%a');
|
||||||
|
|
||||||
-- subqueries are supported in FROM clause
|
-- subqueries are supported in FROM clause
|
||||||
|
|
|
@ -30,8 +30,7 @@ SET
|
||||||
WHERE
|
WHERE
|
||||||
shardid IN (SELECT shardid FROM pg_dist_shard WHERE logicalrelid = 'orders_subquery'::regclass ORDER BY shardid DESC LIMIT 1);
|
shardid IN (SELECT shardid FROM pg_dist_shard WHERE logicalrelid = 'orders_subquery'::regclass ORDER BY shardid DESC LIMIT 1);
|
||||||
|
|
||||||
-- If group by is not on partition column then we error out from single table
|
-- If group by is not on partition column then we recursively plan
|
||||||
-- repartition code path
|
|
||||||
SELECT
|
SELECT
|
||||||
avg(order_count)
|
avg(order_count)
|
||||||
FROM
|
FROM
|
||||||
|
@ -70,9 +69,9 @@ FROM
|
||||||
GROUP BY
|
GROUP BY
|
||||||
l_orderkey) AS unit_prices;
|
l_orderkey) AS unit_prices;
|
||||||
|
|
||||||
-- Subqueries without relation with a volatile functions (non-constant)
|
-- Subqueries without relation with a volatile functions (non-constant) are planned recursively
|
||||||
SELECT count(*) FROM (
|
SELECT count(*) FROM (
|
||||||
SELECT l_orderkey FROM lineitem_subquery JOIN (SELECT random()::int r) sub ON (l_orderkey = r)
|
SELECT l_orderkey FROM lineitem_subquery JOIN (SELECT random()::int r) sub ON (l_orderkey = r) WHERE r > 10
|
||||||
) b;
|
) b;
|
||||||
|
|
||||||
-- Check that we error out if there is non relation subqueries
|
-- Check that we error out if there is non relation subqueries
|
||||||
|
@ -98,7 +97,8 @@ SELECT count(*) FROM
|
||||||
(SELECT l_orderkey FROM lineitem_subquery) UNION
|
(SELECT l_orderkey FROM lineitem_subquery) UNION
|
||||||
(SELECT l_orderkey FROM lineitem_subquery)
|
(SELECT l_orderkey FROM lineitem_subquery)
|
||||||
) b;
|
) b;
|
||||||
-- Check that we error out if inner query has Limit but subquery_pushdown is not set
|
-- we'd error out if inner query has Limit but subquery_pushdown is not set
|
||||||
|
-- but we recursively plan the query
|
||||||
SELECT
|
SELECT
|
||||||
avg(o_totalprice/l_quantity)
|
avg(o_totalprice/l_quantity)
|
||||||
FROM
|
FROM
|
||||||
|
|
|
@ -1120,7 +1120,9 @@ limit 50;
|
||||||
-- reset subquery_pushdown
|
-- reset subquery_pushdown
|
||||||
SET citus.subquery_pushdown to OFF;
|
SET citus.subquery_pushdown to OFF;
|
||||||
|
|
||||||
-- not supported since JOIN is not on the partition key
|
-- we recursively plan recent_events_1
|
||||||
|
-- but not some_users_data since it has a reference
|
||||||
|
-- from an outer query which is not recursively planned
|
||||||
SELECT "some_users_data".user_id, lastseen
|
SELECT "some_users_data".user_id, lastseen
|
||||||
FROM
|
FROM
|
||||||
(SELECT user_id, max(time) AS lastseen
|
(SELECT user_id, max(time) AS lastseen
|
||||||
|
@ -1154,8 +1156,9 @@ ORDER BY
|
||||||
user_id
|
user_id
|
||||||
limit 50;
|
limit 50;
|
||||||
|
|
||||||
-- not supported since JOIN is not on the partition key
|
-- we recursively plan some queries but fail in the end
|
||||||
-- see (2 * user_id as user_id) target list element
|
-- since some_users_data since it has a reference
|
||||||
|
-- from an outer query which is not recursively planned
|
||||||
SELECT "some_users_data".user_id, lastseen
|
SELECT "some_users_data".user_id, lastseen
|
||||||
FROM
|
FROM
|
||||||
(SELECT 2 * user_id as user_id, max(time) AS lastseen
|
(SELECT 2 * user_id as user_id, max(time) AS lastseen
|
||||||
|
@ -1465,7 +1468,9 @@ ORDER BY
|
||||||
user_id DESC
|
user_id DESC
|
||||||
LIMIT 10;
|
LIMIT 10;
|
||||||
|
|
||||||
-- not supported since lower LATERAL JOIN is not on the partition key
|
-- not pushdownable since lower LATERAL JOIN is not on the partition key
|
||||||
|
-- not recursively plannable due to LATERAL join where there is a reference
|
||||||
|
-- from an outer query
|
||||||
SELECT user_id, lastseen
|
SELECT user_id, lastseen
|
||||||
FROM
|
FROM
|
||||||
(SELECT
|
(SELECT
|
||||||
|
@ -1995,7 +2000,9 @@ ORDER BY
|
||||||
LIMIT 10;
|
LIMIT 10;
|
||||||
SET citus.subquery_pushdown to OFF;
|
SET citus.subquery_pushdown to OFF;
|
||||||
|
|
||||||
-- not supported since join is not on the partition key
|
-- not pushdownable since lower LATERAL JOIN is not on the partition key
|
||||||
|
-- not recursively plannable due to LATERAL join where there is a reference
|
||||||
|
-- from an outer query
|
||||||
SELECT *
|
SELECT *
|
||||||
FROM
|
FROM
|
||||||
(SELECT
|
(SELECT
|
||||||
|
|
|
@ -980,14 +980,16 @@ SELECT foo.user_id FROM
|
||||||
WHERE event_type > 100
|
WHERE event_type > 100
|
||||||
) as foo;
|
) as foo;
|
||||||
|
|
||||||
-- not supported since group by is on the reference table column
|
-- not pushdownable since group by is on the reference table column
|
||||||
|
-- recursively planned, but hits unsupported clause type error on the top level query
|
||||||
SELECT foo.user_id FROM
|
SELECT foo.user_id FROM
|
||||||
(
|
(
|
||||||
SELECT r.user_id, random() FROM users_table m JOIN events_reference_table r ON int4eq(m.user_id, r.user_id)
|
SELECT r.user_id, random() FROM users_table m JOIN events_reference_table r ON int4eq(m.user_id, r.user_id)
|
||||||
GROUP BY r.user_id
|
GROUP BY r.user_id
|
||||||
) as foo;
|
) as foo;
|
||||||
|
|
||||||
-- supported since the group by contains at least one distributed table
|
-- not pushdownable since the group by contains at least one distributed table
|
||||||
|
-- recursively planned, but hits unsupported clause type error on the top level query
|
||||||
SELECT foo.user_id FROM
|
SELECT foo.user_id FROM
|
||||||
(
|
(
|
||||||
SELECT r.user_id, random() FROM users_table m JOIN events_reference_table r ON int4eq(m.user_id, r.user_id)
|
SELECT r.user_id, random() FROM users_table m JOIN events_reference_table r ON int4eq(m.user_id, r.user_id)
|
||||||
|
@ -995,7 +997,8 @@ SELECT foo.user_id FROM
|
||||||
) as foo
|
) as foo
|
||||||
ORDER BY 1 LIMIT 3;
|
ORDER BY 1 LIMIT 3;
|
||||||
|
|
||||||
-- not supported since distinct is on the reference table column
|
-- not pushdownable since distinct is on the reference table column
|
||||||
|
-- recursively planned, but hits unsupported clause type error on the top level query
|
||||||
SELECT foo.user_id FROM
|
SELECT foo.user_id FROM
|
||||||
(
|
(
|
||||||
SELECT DISTINCT r.user_id, random() FROM users_table m JOIN events_reference_table r ON int4eq(m.user_id, r.user_id)
|
SELECT DISTINCT r.user_id, random() FROM users_table m JOIN events_reference_table r ON int4eq(m.user_id, r.user_id)
|
||||||
|
@ -1048,7 +1051,8 @@ LIMIT 5
|
||||||
OFFSET 0;
|
OFFSET 0;
|
||||||
|
|
||||||
-- should not push down this query since there is a distributed table (i.e., events_table)
|
-- should not push down this query since there is a distributed table (i.e., events_table)
|
||||||
-- which is not in the DISTINCT clause
|
-- which is not in the DISTINCT clause. Recursive planning also fails since router execution
|
||||||
|
-- is disabled
|
||||||
SELECT * FROM
|
SELECT * FROM
|
||||||
(
|
(
|
||||||
SELECT DISTINCT users_reference_table.user_id FROM users_reference_table, events_table WHERE users_reference_table.user_id = events_table.value_4
|
SELECT DISTINCT users_reference_table.user_id FROM users_reference_table, events_table WHERE users_reference_table.user_id = events_table.value_4
|
||||||
|
@ -1076,6 +1080,8 @@ ORDER BY 1 DESC
|
||||||
LIMIT 4;
|
LIMIT 4;
|
||||||
|
|
||||||
-- should not pushdown since there is a non partition column on the DISTINCT clause
|
-- should not pushdown since there is a non partition column on the DISTINCT clause
|
||||||
|
-- Recursive planning also fails since router execution
|
||||||
|
-- is disabled
|
||||||
SELECT * FROM
|
SELECT * FROM
|
||||||
(
|
(
|
||||||
SELECT
|
SELECT
|
||||||
|
|
|
@ -489,13 +489,14 @@ ORDER BY 1 ASC
|
||||||
LIMIT 2;
|
LIMIT 2;
|
||||||
|
|
||||||
-- subquery in where clause has a volatile function and no relation
|
-- subquery in where clause has a volatile function and no relation
|
||||||
|
-- thus we recursively plan it
|
||||||
SELECT
|
SELECT
|
||||||
user_id
|
user_id
|
||||||
FROM
|
FROM
|
||||||
users_table
|
users_table
|
||||||
WHERE
|
WHERE
|
||||||
value_2 >
|
value_2 >
|
||||||
(SELECT random())
|
(SELECT random()) AND user_id < 0
|
||||||
ORDER BY 1 ASC
|
ORDER BY 1 ASC
|
||||||
LIMIT 2;
|
LIMIT 2;
|
||||||
|
|
||||||
|
@ -519,7 +520,8 @@ WHERE
|
||||||
|
|
||||||
-- we can detect unsupported subquerues even if they appear
|
-- we can detect unsupported subquerues even if they appear
|
||||||
-- in WHERE subquery -> FROM subquery -> WHERE subquery
|
-- in WHERE subquery -> FROM subquery -> WHERE subquery
|
||||||
SELECT user_id
|
-- but we can recursively plan that anyway
|
||||||
|
SELECT DISTINCT user_id
|
||||||
FROM users_table
|
FROM users_table
|
||||||
WHERE user_id
|
WHERE user_id
|
||||||
IN (SELECT
|
IN (SELECT
|
||||||
|
@ -543,7 +545,7 @@ WHERE user_id
|
||||||
AND e1.user_id IN (SELECT user_id FROM users_table LIMIT 3 )
|
AND e1.user_id IN (SELECT user_id FROM users_table LIMIT 3 )
|
||||||
) as f_outer
|
) as f_outer
|
||||||
WHERE f_inner.user_id = f_outer.user_id
|
WHERE f_inner.user_id = f_outer.user_id
|
||||||
);
|
) ORDER BY 1 LIMIT 3;
|
||||||
|
|
||||||
-- semi join is not on the partition key for the third subquery
|
-- semi join is not on the partition key for the third subquery
|
||||||
SELECT user_id
|
SELECT user_id
|
||||||
|
|
|
@ -569,6 +569,8 @@ LIMIT 5;
|
||||||
-- now lets also have some unsupported queries
|
-- now lets also have some unsupported queries
|
||||||
|
|
||||||
-- group by is not on the partition key
|
-- group by is not on the partition key
|
||||||
|
-- but we can still recursively plan it, though that is not suffient for pushdown
|
||||||
|
-- of the whole query
|
||||||
SELECT user_id, sum(counter)
|
SELECT user_id, sum(counter)
|
||||||
FROM (
|
FROM (
|
||||||
SELECT user_id, sum(value_2) AS counter FROM events_table GROUP BY user_id
|
SELECT user_id, sum(value_2) AS counter FROM events_table GROUP BY user_id
|
||||||
|
@ -803,7 +805,9 @@ FROM
|
||||||
(SELECT users_table.user_id FROM events_table, users_table WHERE events_table.user_id = users_table.user_id)
|
(SELECT users_table.user_id FROM events_table, users_table WHERE events_table.user_id = users_table.user_id)
|
||||||
) b;
|
) b;
|
||||||
|
|
||||||
-- we don't support subqueries without relations
|
-- we don't support pushing down subqueries without relations
|
||||||
|
-- recursive planning can replace that query, though the whole
|
||||||
|
-- query is not safe to pushdown
|
||||||
SELECT
|
SELECT
|
||||||
count(*)
|
count(*)
|
||||||
FROM
|
FROM
|
||||||
|
@ -813,7 +817,9 @@ FROM
|
||||||
(SELECT 1)
|
(SELECT 1)
|
||||||
) b;
|
) b;
|
||||||
|
|
||||||
-- we don't support subqueries without relations
|
-- we don't support pushing down subqueries without relations
|
||||||
|
-- recursive planning can replace that query, though the whole
|
||||||
|
-- query is not safe to pushdown
|
||||||
SELECT
|
SELECT
|
||||||
*
|
*
|
||||||
FROM
|
FROM
|
||||||
|
@ -843,6 +849,9 @@ FROM
|
||||||
ORDER BY 1 DESC, 2 DESC
|
ORDER BY 1 DESC, 2 DESC
|
||||||
LIMIT 5;
|
LIMIT 5;
|
||||||
|
|
||||||
|
-- we don't support pushing down subqueries without relations
|
||||||
|
-- recursive planning can replace that query, though the whole
|
||||||
|
-- query is not safe to pushdown
|
||||||
SELECT ("final_query"."event_types") as types, count(*) AS sumOfEventType
|
SELECT ("final_query"."event_types") as types, count(*) AS sumOfEventType
|
||||||
FROM
|
FROM
|
||||||
( SELECT *, random()
|
( SELECT *, random()
|
||||||
|
|
|
@ -146,8 +146,8 @@ SET citus.task_executor_type to DEFAULT;
|
||||||
CREATE VIEW lineitems_by_shipping_method AS
|
CREATE VIEW lineitems_by_shipping_method AS
|
||||||
SELECT l_shipmode, count(*) as cnt FROM lineitem_hash_part GROUP BY 1;
|
SELECT l_shipmode, count(*) as cnt FROM lineitem_hash_part GROUP BY 1;
|
||||||
|
|
||||||
-- following will fail due to non GROUP BY of partition key
|
-- following will be supported via recursive planning
|
||||||
SELECT * FROM lineitems_by_shipping_method;
|
SELECT * FROM lineitems_by_shipping_method ORDER BY 1,2 LIMIT 5;
|
||||||
|
|
||||||
-- create a view with group by on partition column
|
-- create a view with group by on partition column
|
||||||
CREATE VIEW lineitems_by_orderkey AS
|
CREATE VIEW lineitems_by_orderkey AS
|
||||||
|
@ -348,18 +348,19 @@ CREATE VIEW distinct_user_with_value_1_3 AS SELECT DISTINCT user_id FROM users_t
|
||||||
SELECT * FROM distinct_user_with_value_1_3 ORDER BY user_id;
|
SELECT * FROM distinct_user_with_value_1_3 ORDER BY user_id;
|
||||||
|
|
||||||
-- distinct is not supported if it is on a non-partition key
|
-- distinct is not supported if it is on a non-partition key
|
||||||
|
-- but will be supported via recursive planning
|
||||||
CREATE VIEW distinct_value_1 AS SELECT DISTINCT value_1 FROM users_table WHERE value_2 = 3;
|
CREATE VIEW distinct_value_1 AS SELECT DISTINCT value_1 FROM users_table WHERE value_2 = 3;
|
||||||
SELECT * FROM distinct_value_1;
|
SELECT * FROM distinct_value_1 ORDER BY 1 DESC LIMIT 5;
|
||||||
|
|
||||||
-- CTEs are not supported even if they are on views
|
-- CTEs are supported even if they are on views
|
||||||
CREATE VIEW cte_view_1 AS
|
CREATE VIEW cte_view_1 AS
|
||||||
WITH c1 AS (SELECT * FROM users_table WHERE value_1 = 3) SELECT * FROM c1 WHERE value_2 < 4;
|
WITH c1 AS (SELECT * FROM users_table WHERE value_1 = 3) SELECT * FROM c1 WHERE value_2 < 4;
|
||||||
|
|
||||||
SELECT * FROM cte_view_1;
|
SELECT * FROM cte_view_1 ORDER BY 1,2,3,4,5 LIMIT 5;
|
||||||
|
|
||||||
-- this is single shard query but still not supported since it has view + cte
|
-- this is single shard query and still not supported since it has view + cte
|
||||||
-- router planner can't detect it
|
-- router planner can't detect it
|
||||||
SELECT * FROM cte_view_1 WHERE user_id = 2;
|
SELECT * FROM cte_view_1 WHERE user_id = 2 ORDER BY 1,2,3,4,5;
|
||||||
|
|
||||||
-- if CTE itself prunes down to a single shard than the view is supported (router plannable)
|
-- if CTE itself prunes down to a single shard than the view is supported (router plannable)
|
||||||
CREATE VIEW cte_view_2 AS
|
CREATE VIEW cte_view_2 AS
|
||||||
|
|
|
@ -0,0 +1,160 @@
|
||||||
|
-- ===================================================================
|
||||||
|
-- test recursive planning functionality with subqueries and CTEs
|
||||||
|
-- ===================================================================
|
||||||
|
CREATE SCHEMA subquery_deep;
|
||||||
|
SET search_path TO subquery_and_ctes, public;
|
||||||
|
|
||||||
|
SET client_min_messages TO DEBUG1;
|
||||||
|
|
||||||
|
-- subquery in FROM -> FROM -> FROM should be replaced due to OFFSET
|
||||||
|
-- one level up subquery should be replaced due to GROUP BY on non partition key
|
||||||
|
-- one level up subquery should be replaced due to LIMUT
|
||||||
|
SELECT
|
||||||
|
DISTINCT user_id
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT users_table.user_id FROM users_table,
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
avg(event_type) as avg_val
|
||||||
|
FROM
|
||||||
|
(SELECT event_type, users_table.user_id FROM users_table,
|
||||||
|
(SELECT user_id, event_type FROM events_table WHERE value_2 < 3 OFFSET 3) as foo
|
||||||
|
WHERE foo.user_id = users_table.user_id
|
||||||
|
) bar, users_table WHERE bar.user_id = users_table.user_id GROUP BY users_table.value_1
|
||||||
|
|
||||||
|
) as baz
|
||||||
|
WHERE baz.avg_val < users_table.user_id
|
||||||
|
LIMIT 3
|
||||||
|
|
||||||
|
) as sub1
|
||||||
|
ORDER BY 1 DESC;
|
||||||
|
|
||||||
|
-- subquery in FROM -> FROM -> WHERE -> WHERE should be replaced due to CTE
|
||||||
|
-- subquery in FROM -> FROM -> WHERE should be replaced due to LIMIT
|
||||||
|
-- one level above should be replaced due to DISTINCT on non-partition key
|
||||||
|
-- one level above should be replaced due to GROUP BY on non-partition key
|
||||||
|
SELECT event, array_length(events_table, 1)
|
||||||
|
FROM (
|
||||||
|
SELECT event, array_agg(t.user_id) AS events_table
|
||||||
|
FROM (
|
||||||
|
SELECT
|
||||||
|
DISTINCT ON(e.event_type::text) e.event_type::text as event, e.time, e.user_id
|
||||||
|
FROM
|
||||||
|
users_table AS u,
|
||||||
|
events_table AS e
|
||||||
|
WHERE u.user_id = e.user_id AND
|
||||||
|
u.user_id IN
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
user_id
|
||||||
|
FROM
|
||||||
|
users_table
|
||||||
|
WHERE value_2 >= 5
|
||||||
|
AND EXISTS (SELECT user_id FROM events_table WHERE event_type > 1 AND event_type <= 3 AND value_3 > 1 AND user_id = users_table.user_id)
|
||||||
|
AND NOT EXISTS (SELECT user_id FROM events_table WHERE event_type > 3 AND event_type <= 4 AND value_3 > 1 AND user_id = users_table.user_id)
|
||||||
|
AND EXISTS (WITH cte AS (SELECT count(*) FROM users_table) SELECT * FROM cte)
|
||||||
|
LIMIT 5
|
||||||
|
)
|
||||||
|
) t, users_table WHERE users_table.value_1 = t.event::int
|
||||||
|
GROUP BY event
|
||||||
|
) q
|
||||||
|
ORDER BY 2 DESC, 1;
|
||||||
|
|
||||||
|
-- this test probably doesn't add too much value,
|
||||||
|
-- but recurse 6 times for fun
|
||||||
|
|
||||||
|
SELECT count(*)
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT avg(min) FROM
|
||||||
|
(
|
||||||
|
SELECT min(users_table.value_1) FROM
|
||||||
|
(
|
||||||
|
SELECT avg(event_type) as avg_ev_type FROM
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
max(value_1) as mx_val_1
|
||||||
|
FROM (
|
||||||
|
SELECT
|
||||||
|
avg(event_type) as avg
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
cnt
|
||||||
|
FROM
|
||||||
|
(SELECT count(*) as cnt, value_2 FROM users_table GROUP BY value_2) as level_1, users_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = level_1.cnt
|
||||||
|
) as level_2, events_table
|
||||||
|
WHERE events_table.user_id = level_2.cnt
|
||||||
|
GROUP BY level_2.cnt
|
||||||
|
) as level_3, users_table
|
||||||
|
WHERE user_id = level_3.avg
|
||||||
|
GROUP BY level_3.avg
|
||||||
|
) as level_4, events_table
|
||||||
|
WHERE level_4.mx_val_1 = events_table.user_id
|
||||||
|
GROUP BY level_4.mx_val_1
|
||||||
|
) as level_5, users_table
|
||||||
|
WHERE
|
||||||
|
level_5.avg_ev_type = users_table.user_id
|
||||||
|
GROUP BY
|
||||||
|
level_5.avg_ev_type
|
||||||
|
) as level_6, users_table WHERE users_table.user_id = level_6.min
|
||||||
|
GROUP BY users_table.value_1
|
||||||
|
) as bar;
|
||||||
|
|
||||||
|
-- same query happening in the subqueries in WHERE
|
||||||
|
|
||||||
|
-- this test probably doesn't add too much value,
|
||||||
|
-- but recurse 6 times for fun
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
users_table
|
||||||
|
WHERE user_id IN (
|
||||||
|
SELECT count(*)
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT avg(min) FROM
|
||||||
|
(
|
||||||
|
SELECT min(users_table.value_1) FROM
|
||||||
|
(
|
||||||
|
SELECT avg(event_type) as avg_ev_type FROM
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
max(value_1) as mx_val_1
|
||||||
|
FROM (
|
||||||
|
SELECT
|
||||||
|
avg(event_type) as avg
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
cnt
|
||||||
|
FROM
|
||||||
|
(SELECT count(*) as cnt, value_2 FROM users_table GROUP BY value_2) as level_1, users_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = level_1.cnt
|
||||||
|
) as level_2, events_table
|
||||||
|
WHERE events_table.user_id = level_2.cnt
|
||||||
|
GROUP BY level_2.cnt
|
||||||
|
) as level_3, users_table
|
||||||
|
WHERE user_id = level_3.avg
|
||||||
|
GROUP BY level_3.avg
|
||||||
|
) as level_4, events_table
|
||||||
|
WHERE level_4.mx_val_1 = events_table.user_id
|
||||||
|
GROUP BY level_4.mx_val_1
|
||||||
|
) as level_5, users_table
|
||||||
|
WHERE
|
||||||
|
level_5.avg_ev_type = users_table.user_id
|
||||||
|
GROUP BY
|
||||||
|
level_5.avg_ev_type
|
||||||
|
) as level_6, users_table WHERE users_table.user_id = level_6.min
|
||||||
|
GROUP BY users_table.value_1
|
||||||
|
) as bar);
|
||||||
|
|
||||||
|
|
||||||
|
SET client_min_messages TO DEFAULT;
|
||||||
|
|
||||||
|
DROP SCHEMA subquery_deep CASCADE;
|
||||||
|
SET search_path TO public;
|
|
@ -0,0 +1,137 @@
|
||||||
|
-- ===================================================================
|
||||||
|
-- test recursive planning functionality on failure cases
|
||||||
|
-- ===================================================================
|
||||||
|
CREATE SCHEMA not_supported;
|
||||||
|
SET search_path TO not_supported, public;
|
||||||
|
|
||||||
|
SET client_min_messages TO DEBUG1;
|
||||||
|
|
||||||
|
CREATE TABLE users_table_local AS SELECT * FROM users_table;
|
||||||
|
|
||||||
|
-- we don't support subqueries with local tables when they are not leaf queries
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
users_table_local.user_id
|
||||||
|
FROM
|
||||||
|
users_table_local, (SELECT user_id FROM events_table) as evs
|
||||||
|
WHERE users_table_local.user_id = evs.user_id
|
||||||
|
) as foo;
|
||||||
|
|
||||||
|
-- we don't support subqueries with local tables when they are not leaf queries
|
||||||
|
SELECT user_id FROM users_table WHERE user_id IN
|
||||||
|
(SELECT
|
||||||
|
user_id
|
||||||
|
FROM
|
||||||
|
users_table_local JOIN (SELECT user_id FROM events_table_local) as foo
|
||||||
|
USING (user_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- we don't support aggregate distinct if the group by is not on partition key, expect for count distinct
|
||||||
|
-- thus baz and bar are recursively planned but not foo
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT avg(DISTINCT value_1), random() FROM users_table GROUP BY user_id OFFSET 3
|
||||||
|
) as baz,
|
||||||
|
(
|
||||||
|
SELECT count(DISTINCT value_1), random() FROM users_table GROUP BY value_2 OFFSET 3
|
||||||
|
) as bar,
|
||||||
|
(
|
||||||
|
SELECT avg(DISTINCT value_1), random() FROM users_table GROUP BY value_2 OFFSET 3
|
||||||
|
) as foo;
|
||||||
|
|
||||||
|
-- we don't support array_aggs with ORDER BYs
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
array_agg(users_table.user_id ORDER BY users_table.time)
|
||||||
|
FROM
|
||||||
|
users_table, (SELECT user_id FROM events_table) as evs
|
||||||
|
WHERE users_table.user_id = evs.user_id
|
||||||
|
GROUP BY users_table.user_id
|
||||||
|
LIMIT 5
|
||||||
|
) as foo;
|
||||||
|
|
||||||
|
-- we don't support queries with recurring tuples in the FROM
|
||||||
|
-- clause and subquery in WHERE clause
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
users_table.user_id
|
||||||
|
FROM
|
||||||
|
users_table, (SELECT user_id FROM events_table) as evs
|
||||||
|
WHERE users_table.user_id = evs.user_id
|
||||||
|
LIMIT 5
|
||||||
|
) as foo WHERE user_id IN (SELECT count(*) FROM users_table GROUP BY user_id);
|
||||||
|
|
||||||
|
-- we don't support recursive subqueries when router executor is disabled
|
||||||
|
SET citus.enable_router_execution TO false;
|
||||||
|
SELECT
|
||||||
|
user_id
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
DISTINCT users_table.user_id
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
ORDER BY 1 DESC LIMIT 5
|
||||||
|
) as foo
|
||||||
|
ORDER BY 1 DESC;
|
||||||
|
SET citus.enable_router_execution TO true;
|
||||||
|
|
||||||
|
|
||||||
|
-- window functions are not allowed if they're not partitioned on the distribution column
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
user_id, time, rnk
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
*, rank() OVER my_win as rnk
|
||||||
|
FROM
|
||||||
|
events_table
|
||||||
|
WINDOW my_win AS (PARTITION BY event_type ORDER BY time DESC)
|
||||||
|
) as foo
|
||||||
|
ORDER BY
|
||||||
|
3 DESC, 1 DESC, 2 DESC
|
||||||
|
LIMIT
|
||||||
|
10) as foo;
|
||||||
|
|
||||||
|
-- top level join is not on the distribution key thus not supported
|
||||||
|
-- (use random to prevent Postgres to pull subqueries)
|
||||||
|
SELECT
|
||||||
|
foo.value_2
|
||||||
|
FROM
|
||||||
|
(SELECT users_table.value_2, random() FROM users_table, events_table WHERE users_table.user_id = events_table.user_id AND event_type IN (1,2,3,4)) as foo,
|
||||||
|
(SELECT users_table.value_2 FROM users_table, events_table WHERE users_table.user_id = events_table.user_id AND event_type IN (5,6,7,8)) as bar
|
||||||
|
WHERE
|
||||||
|
foo.value_2 = bar.value_2;
|
||||||
|
|
||||||
|
|
||||||
|
-- OUTER JOINs where the outer part is recursively planned and not the other way
|
||||||
|
-- around is not supported
|
||||||
|
SELECT
|
||||||
|
foo.value_2
|
||||||
|
FROM
|
||||||
|
(SELECT users_table.value_2 FROM users_table, events_table WHERE users_table.user_id = events_table.user_id AND event_type IN (1,2,3,4) LIMIT 5) as foo
|
||||||
|
LEFT JOIN
|
||||||
|
(SELECT users_table.value_2 FROM users_table, events_table WHERE users_table.user_id = events_table.user_id AND event_type IN (5,6,7,8)) as bar
|
||||||
|
ON(foo.value_2 = bar.value_2);
|
||||||
|
|
||||||
|
SET client_min_messages TO DEFAULT;
|
||||||
|
|
||||||
|
DROP SCHEMA not_supported CASCADE;
|
||||||
|
SET search_path TO public;
|
|
@ -0,0 +1,326 @@
|
||||||
|
-- ===================================================================
|
||||||
|
-- test recursive planning functionality with subqueries and CTEs
|
||||||
|
-- ===================================================================
|
||||||
|
CREATE SCHEMA subquery_and_ctes;
|
||||||
|
SET search_path TO subquery_and_ctes, public;
|
||||||
|
|
||||||
|
|
||||||
|
CREATE TABLE users_table_local AS SELECT * FROM users_table;
|
||||||
|
|
||||||
|
SET client_min_messages TO DEBUG1;
|
||||||
|
|
||||||
|
-- CTEs are recursively planned, and subquery foo is also recursively planned
|
||||||
|
-- final plan becomes a router plan
|
||||||
|
WITH cte AS (
|
||||||
|
WITH local_cte AS (
|
||||||
|
SELECT * FROM users_table_local
|
||||||
|
),
|
||||||
|
dist_cte AS (
|
||||||
|
SELECT user_id FROM events_table
|
||||||
|
)
|
||||||
|
SELECT dist_cte.user_id FROM local_cte join dist_cte on dist_cte.user_id=local_cte.user_id
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
count(*)
|
||||||
|
FROM
|
||||||
|
cte,
|
||||||
|
(SELECT
|
||||||
|
DISTINCT users_table.user_id
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
ORDER BY 1 DESC LIMIT 5
|
||||||
|
) as foo
|
||||||
|
WHERE foo.user_id = cte.user_id;
|
||||||
|
|
||||||
|
-- CTEs are recursively planned, and subquery foo is also recursively planned
|
||||||
|
-- final plan becomes a real-time plan since we also have events_table in the
|
||||||
|
-- range table entries
|
||||||
|
WITH cte AS (
|
||||||
|
WITH local_cte AS (
|
||||||
|
SELECT * FROM users_table_local
|
||||||
|
),
|
||||||
|
dist_cte AS (
|
||||||
|
SELECT user_id FROM events_table
|
||||||
|
)
|
||||||
|
SELECT dist_cte.user_id FROM local_cte join dist_cte on dist_cte.user_id=local_cte.user_id
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
count(*)
|
||||||
|
FROM
|
||||||
|
cte,
|
||||||
|
(SELECT
|
||||||
|
DISTINCT users_table.user_id
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
ORDER BY 1 DESC LIMIT 5
|
||||||
|
) as foo, events_table
|
||||||
|
WHERE foo.user_id = cte.user_id AND events_table.user_id = cte.user_id;
|
||||||
|
|
||||||
|
-- CTEs are replaced and subquery in WHERE is also replaced
|
||||||
|
-- but the query is still real-time query since users_table is in the
|
||||||
|
-- range table list
|
||||||
|
WITH cte AS (
|
||||||
|
WITH local_cte AS (
|
||||||
|
SELECT * FROM users_table_local
|
||||||
|
),
|
||||||
|
dist_cte AS (
|
||||||
|
SELECT user_id FROM events_table
|
||||||
|
)
|
||||||
|
SELECT dist_cte.user_id FROM local_cte join dist_cte on dist_cte.user_id=local_cte.user_id
|
||||||
|
)
|
||||||
|
SELECT DISTINCT cte.user_id
|
||||||
|
FROM users_table, cte
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = cte.user_id AND
|
||||||
|
users_table.user_id IN (SELECT DISTINCT value_2 FROM users_table WHERE value_1 >= 1 AND value_1 <= 20 ORDER BY 1 LIMIT 5)
|
||||||
|
ORDER BY 1 DESC;
|
||||||
|
|
||||||
|
-- a very similar query as the above, but this time errors
|
||||||
|
-- out since we don't support subqueries in WHERE clause
|
||||||
|
-- when there is only intermediate results on the range table
|
||||||
|
-- note that this time subquery in WHERE clause is not replaced
|
||||||
|
WITH cte AS (
|
||||||
|
WITH local_cte AS (
|
||||||
|
SELECT * FROM users_table_local
|
||||||
|
),
|
||||||
|
dist_cte AS (
|
||||||
|
SELECT user_id FROM events_table
|
||||||
|
)
|
||||||
|
SELECT dist_cte.user_id FROM local_cte join dist_cte on dist_cte.user_id=local_cte.user_id
|
||||||
|
)
|
||||||
|
SELECT DISTINCT cte.user_id
|
||||||
|
FROM cte
|
||||||
|
WHERE
|
||||||
|
cte.user_id IN (SELECT DISTINCT user_id FROM users_table WHERE value_1 >= 1 AND value_1 <= 20)
|
||||||
|
ORDER BY 1 DESC;
|
||||||
|
|
||||||
|
-- CTEs inside a subquery and the final query becomes a router
|
||||||
|
-- query
|
||||||
|
SELECT
|
||||||
|
user_id
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
WITH cte AS (
|
||||||
|
SELECT
|
||||||
|
DISTINCT users_table.user_id
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
) SELECT * FROM cte ORDER BY 1 DESC
|
||||||
|
) as foo;
|
||||||
|
|
||||||
|
|
||||||
|
-- CTEs inside a subquery and the final query becomes a
|
||||||
|
-- real-time query since the other subquery is safe to pushdown
|
||||||
|
SELECT
|
||||||
|
bar.user_id
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
WITH cte AS (
|
||||||
|
SELECT
|
||||||
|
DISTINCT users_table.user_id
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
) SELECT * FROM cte ORDER BY 1 DESC
|
||||||
|
) as foo,
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
DISTINCT users_table.user_id
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
|
||||||
|
) as bar
|
||||||
|
WHERE foo.user_id = bar.user_id;
|
||||||
|
|
||||||
|
-- CTEs inside a deeper subquery
|
||||||
|
-- and also the subquery that contains the CTE is replaced
|
||||||
|
SELECT
|
||||||
|
DISTINCT bar.user_id
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
WITH cte AS (
|
||||||
|
SELECT
|
||||||
|
DISTINCT users_table.user_id
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
) SELECT * FROM cte ORDER BY 1 DESC
|
||||||
|
) as foo,
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
users_table.user_id, some_events.event_type
|
||||||
|
FROM
|
||||||
|
users_table,
|
||||||
|
(
|
||||||
|
WITH cte AS (
|
||||||
|
SELECT
|
||||||
|
event_type, users_table.user_id
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
value_1 IN (1,2)
|
||||||
|
) SELECT * FROM cte ORDER BY 1 DESC
|
||||||
|
) as some_events
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = some_events.user_id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
ORDER BY 2,1
|
||||||
|
LIMIT 2
|
||||||
|
|
||||||
|
) as bar
|
||||||
|
WHERE foo.user_id = bar.user_id
|
||||||
|
ORDER BY 1 DESC LIMIT 5;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- CTEs on the different parts of the query is replaced
|
||||||
|
-- and subquery foo is also replaced since it contains
|
||||||
|
-- DISTINCT on a non-partition key
|
||||||
|
SELECT * FROM
|
||||||
|
(
|
||||||
|
WITH cte AS (
|
||||||
|
WITH local_cte AS (
|
||||||
|
SELECT * FROM users_table_local
|
||||||
|
),
|
||||||
|
dist_cte AS (
|
||||||
|
SELECT user_id FROM events_table
|
||||||
|
)
|
||||||
|
SELECT dist_cte.user_id FROM local_cte join dist_cte on dist_cte.user_id=local_cte.user_id
|
||||||
|
)
|
||||||
|
SELECT DISTINCT cte.user_id
|
||||||
|
FROM users_table, cte
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = cte.user_id AND
|
||||||
|
users_table.user_id IN
|
||||||
|
(WITH cte_in_where AS (SELECT DISTINCT value_2 FROM users_table WHERE value_1 >= 1 AND value_1 <= 20 ORDER BY 1 LIMIT 5) SELECT * FROM cte_in_where)
|
||||||
|
ORDER BY 1 DESC
|
||||||
|
) as foo,
|
||||||
|
events_table
|
||||||
|
WHERE
|
||||||
|
foo.user_id = events_table.value_2
|
||||||
|
ORDER BY 3 DESC, 2 DESC, 1 DESC
|
||||||
|
LIMIT 5;
|
||||||
|
|
||||||
|
|
||||||
|
-- now recursively plan subqueries inside the CTEs that contains LIMIT and OFFSET
|
||||||
|
WITH cte AS (
|
||||||
|
WITH local_cte AS (
|
||||||
|
SELECT * FROM users_table_local
|
||||||
|
),
|
||||||
|
dist_cte AS (
|
||||||
|
SELECT
|
||||||
|
user_id
|
||||||
|
FROM
|
||||||
|
events_table,
|
||||||
|
(SELECT DISTINCT value_2 FROM users_table OFFSET 0) as foo
|
||||||
|
WHERE
|
||||||
|
events_table.user_id = foo.value_2 AND
|
||||||
|
events_table.user_id IN (SELECT DISTINCT value_1 FROM users_table ORDER BY 1 LIMIT 3)
|
||||||
|
)
|
||||||
|
SELECT dist_cte.user_id FROM local_cte join dist_cte on dist_cte.user_id=local_cte.user_id
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
count(*)
|
||||||
|
FROM
|
||||||
|
cte,
|
||||||
|
(SELECT
|
||||||
|
DISTINCT users_table.user_id
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
ORDER BY 1 DESC LIMIT 5
|
||||||
|
) as foo
|
||||||
|
WHERE foo.user_id = cte.user_id;
|
||||||
|
|
||||||
|
-- the same query, but this time the CTEs also live inside a subquery
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
|
||||||
|
WITH cte AS (
|
||||||
|
WITH local_cte AS (
|
||||||
|
SELECT * FROM users_table_local
|
||||||
|
),
|
||||||
|
dist_cte AS (
|
||||||
|
SELECT
|
||||||
|
user_id
|
||||||
|
FROM
|
||||||
|
events_table,
|
||||||
|
(SELECT DISTINCT value_2 FROM users_table OFFSET 0) as foo
|
||||||
|
WHERE
|
||||||
|
events_table.user_id = foo.value_2 AND
|
||||||
|
events_table.user_id IN (SELECT DISTINCT value_1 FROM users_table ORDER BY 1 LIMIT 3)
|
||||||
|
)
|
||||||
|
SELECT dist_cte.user_id FROM local_cte join dist_cte on dist_cte.user_id=local_cte.user_id
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
count(*) as cnt
|
||||||
|
FROM
|
||||||
|
cte,
|
||||||
|
(SELECT
|
||||||
|
DISTINCT users_table.user_id
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
ORDER BY 1 DESC LIMIT 5
|
||||||
|
) as foo
|
||||||
|
WHERE foo.user_id = cte.user_id
|
||||||
|
|
||||||
|
) as foo, users_table WHERE foo.cnt > users_table.value_2
|
||||||
|
ORDER BY 3 DESC, 1 DESC, 2 DESC, 4 DESC
|
||||||
|
LIMIT 5;
|
||||||
|
|
||||||
|
-- recursive CTES are not supported inside subqueries as well
|
||||||
|
SELECT
|
||||||
|
bar.user_id
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
WITH RECURSIVE cte AS (
|
||||||
|
SELECT
|
||||||
|
DISTINCT users_table.user_id
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
) SELECT * FROM cte ORDER BY 1 DESC
|
||||||
|
) as foo,
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
DISTINCT users_table.user_id
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
|
||||||
|
) as bar
|
||||||
|
WHERE foo.user_id = bar.user_id;
|
||||||
|
|
||||||
|
|
||||||
|
SET client_min_messages TO DEFAULT;
|
||||||
|
|
||||||
|
DROP SCHEMA subquery_and_ctes CASCADE;
|
||||||
|
SET search_path TO public;
|
|
@ -0,0 +1,268 @@
|
||||||
|
-- ===================================================================
|
||||||
|
-- test recursive planning functionality
|
||||||
|
-- ===================================================================
|
||||||
|
|
||||||
|
SET client_min_messages TO DEBUG1;
|
||||||
|
|
||||||
|
-- subqueries in FROM clause with LIMIT should be recursively planned
|
||||||
|
SELECT
|
||||||
|
user_id
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
DISTINCT users_table.user_id
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
ORDER BY 1 DESC LIMIT 5
|
||||||
|
) as foo
|
||||||
|
ORDER BY 1 DESC;
|
||||||
|
|
||||||
|
|
||||||
|
-- subqueries in FROM clause with DISTINCT on non-partition key
|
||||||
|
-- should be recursively planned
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
DISTINCT users_table.value_1
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
ORDER BY 1
|
||||||
|
) as foo
|
||||||
|
ORDER BY 1 DESC;
|
||||||
|
|
||||||
|
-- subqueries in FROM clause with GROUP BY on non-partition key
|
||||||
|
-- should be recursively planned
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
users_table.value_2, avg(value_1)
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
GROUP BY users_table.value_2
|
||||||
|
ORDER BY 1 DESC
|
||||||
|
) as foo
|
||||||
|
ORDER BY 2 DESC, 1;
|
||||||
|
|
||||||
|
-- multiple subqueries in FROM clause should be replaced
|
||||||
|
-- and the final query is router query
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
users_table.value_2
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
GROUP BY users_table.value_2
|
||||||
|
ORDER BY 1 DESC
|
||||||
|
) as foo,
|
||||||
|
(SELECT
|
||||||
|
users_table.value_3
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (5,6,7,8)
|
||||||
|
GROUP BY users_table.value_3
|
||||||
|
ORDER BY 1 DESC
|
||||||
|
) as bar
|
||||||
|
WHERE foo.value_2 = bar.value_3
|
||||||
|
ORDER BY 2 DESC, 1;
|
||||||
|
|
||||||
|
-- same query with alias in the subquery
|
||||||
|
SELECT
|
||||||
|
DISTINCT ON (citus) citus, postgres, citus + 1 as c1, postgres-1 as p1
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
users_table.value_2
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
GROUP BY users_table.value_2
|
||||||
|
ORDER BY 1 DESC
|
||||||
|
) as foo(postgres),
|
||||||
|
(SELECT
|
||||||
|
users_table.user_id
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (5,6,7,8)
|
||||||
|
ORDER BY 1 DESC
|
||||||
|
) as bar (citus)
|
||||||
|
WHERE foo.postgres = bar.citus
|
||||||
|
ORDER BY 1 DESC, 2 DESC
|
||||||
|
LIMIT 3;
|
||||||
|
|
||||||
|
-- foo is replaced
|
||||||
|
-- and the final query is real-time
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
users_table.value_2
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
GROUP BY users_table.value_2
|
||||||
|
ORDER BY 1 DESC
|
||||||
|
) as foo,
|
||||||
|
(SELECT
|
||||||
|
users_table.user_id
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (5,6,7,8)
|
||||||
|
ORDER BY 1 DESC
|
||||||
|
) as bar
|
||||||
|
WHERE foo.value_2 = bar.user_id
|
||||||
|
ORDER BY 2 DESC, 1 DESC
|
||||||
|
LIMIT 3;
|
||||||
|
|
||||||
|
-- subqueries in WHERE should be replaced
|
||||||
|
SELECT DISTINCT user_id
|
||||||
|
FROM users_table
|
||||||
|
WHERE
|
||||||
|
user_id IN (SELECT DISTINCT value_2 FROM users_table WHERE value_1 >= 1 AND value_1 <= 20 ORDER BY 1 LIMIT 5)
|
||||||
|
ORDER BY 1 DESC;
|
||||||
|
|
||||||
|
-- subquery in FROM -> FROM -> FROM should be replaced due to OFFSET
|
||||||
|
SELECT
|
||||||
|
DISTINCT user_id
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT users_table.user_id FROM users_table,
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
event_type, user_id
|
||||||
|
FROM
|
||||||
|
(SELECT event_type, users_table.user_id FROM users_table,
|
||||||
|
(SELECT user_id, event_type FROM events_table WHERE value_2 < 3 OFFSET 3) as foo
|
||||||
|
WHERE foo.user_id = users_table.user_id
|
||||||
|
) bar
|
||||||
|
|
||||||
|
) as baz
|
||||||
|
WHERE baz.user_id = users_table.user_id
|
||||||
|
|
||||||
|
) as sub1
|
||||||
|
ORDER BY 1 DESC
|
||||||
|
LIMIT 3;
|
||||||
|
|
||||||
|
|
||||||
|
-- subquery in FROM -> FROM -> WHERE should be replaced due to LIMIT
|
||||||
|
SELECT user_id, array_length(events_table, 1)
|
||||||
|
FROM (
|
||||||
|
SELECT user_id, array_agg(event ORDER BY time) AS events_table
|
||||||
|
FROM (
|
||||||
|
SELECT
|
||||||
|
u.user_id, e.event_type::text AS event, e.time
|
||||||
|
FROM
|
||||||
|
users_table AS u,
|
||||||
|
events_table AS e
|
||||||
|
WHERE u.user_id = e.user_id AND
|
||||||
|
u.user_id IN
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
user_id
|
||||||
|
FROM
|
||||||
|
users_table
|
||||||
|
WHERE value_2 >= 5
|
||||||
|
AND EXISTS (SELECT user_id FROM events_table WHERE event_type > 1 AND event_type <= 3 AND value_3 > 1 AND user_id = users_table.user_id)
|
||||||
|
AND NOT EXISTS (SELECT user_id FROM events_table WHERE event_type > 3 AND event_type <= 4 AND value_3 > 1 AND user_id = users_table.user_id)
|
||||||
|
LIMIT 5
|
||||||
|
)
|
||||||
|
) t
|
||||||
|
GROUP BY user_id
|
||||||
|
) q
|
||||||
|
ORDER BY 2 DESC, 1;
|
||||||
|
|
||||||
|
|
||||||
|
-- subquery (i.e., subquery_2) in WHERE->FROM should be replaced due to LIMIT
|
||||||
|
SELECT
|
||||||
|
user_id
|
||||||
|
FROM
|
||||||
|
users_table
|
||||||
|
WHERE
|
||||||
|
user_id IN
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
user_id
|
||||||
|
FROM (
|
||||||
|
SELECT
|
||||||
|
subquery_1.user_id, count_pay
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
(SELECT
|
||||||
|
users_table.user_id,
|
||||||
|
'action=>1' AS event,
|
||||||
|
events_table.time
|
||||||
|
FROM
|
||||||
|
users_table,
|
||||||
|
events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
users_table.user_id >= 1 AND
|
||||||
|
users_table.user_id <= 3 AND
|
||||||
|
events_table.event_type > 1 AND events_table.event_type < 3
|
||||||
|
)
|
||||||
|
UNION
|
||||||
|
(SELECT
|
||||||
|
users_table.user_id,
|
||||||
|
'action=>2' AS event,
|
||||||
|
events_table.time
|
||||||
|
FROM
|
||||||
|
users_table,
|
||||||
|
events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
users_table.user_id >= 1 AND
|
||||||
|
users_table.user_id <= 3 AND
|
||||||
|
events_table.event_type > 2 AND events_table.event_type < 4
|
||||||
|
)
|
||||||
|
) AS subquery_1
|
||||||
|
LEFT JOIN
|
||||||
|
(SELECT
|
||||||
|
user_id,
|
||||||
|
COUNT(*) AS count_pay
|
||||||
|
FROM
|
||||||
|
users_table
|
||||||
|
WHERE
|
||||||
|
user_id >= 1 AND
|
||||||
|
user_id <= 3 AND
|
||||||
|
users_table.value_1 > 3 AND users_table.value_1 < 5
|
||||||
|
GROUP BY
|
||||||
|
user_id
|
||||||
|
HAVING
|
||||||
|
COUNT(*) > 1
|
||||||
|
LIMIT 10
|
||||||
|
|
||||||
|
) AS subquery_2
|
||||||
|
ON
|
||||||
|
subquery_1.user_id = subquery_2.user_id
|
||||||
|
GROUP BY
|
||||||
|
subquery_1.user_id,
|
||||||
|
count_pay) AS subquery_top
|
||||||
|
GROUP BY
|
||||||
|
count_pay, user_id
|
||||||
|
)
|
||||||
|
GROUP BY user_id
|
||||||
|
HAVING count(*) > 1 AND sum(value_2) > 29
|
||||||
|
ORDER BY 1;
|
||||||
|
|
|
@ -0,0 +1,113 @@
|
||||||
|
-- ===================================================================
|
||||||
|
-- test recursive planning functionality with different executors
|
||||||
|
-- ===================================================================
|
||||||
|
CREATE SCHEMA subquery_executor;
|
||||||
|
SET search_path TO subquery_executor, public;
|
||||||
|
|
||||||
|
|
||||||
|
CREATE TABLE users_table_local AS SELECT * FROM users_table;
|
||||||
|
|
||||||
|
SET client_min_messages TO DEBUG1;
|
||||||
|
|
||||||
|
-- subquery with router planner
|
||||||
|
SELECT
|
||||||
|
count(*)
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT value_2 FROM users_table WHERE user_id = 15 OFFSET 0
|
||||||
|
) as foo,
|
||||||
|
(
|
||||||
|
SELECT user_id FROM users_table
|
||||||
|
) as bar
|
||||||
|
WHERE foo.value_2 = bar.user_id;
|
||||||
|
|
||||||
|
-- subquery with router but not logical plannable
|
||||||
|
-- should fail
|
||||||
|
SELECT
|
||||||
|
count(*)
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT user_id, sum(value_2) over (partition by user_id) AS counter FROM users_table WHERE user_id = 15
|
||||||
|
) as foo,
|
||||||
|
(
|
||||||
|
SELECT user_id FROM users_table
|
||||||
|
) as bar
|
||||||
|
WHERE foo.counter = bar.user_id;
|
||||||
|
|
||||||
|
-- subquery with real-time query
|
||||||
|
SELECT
|
||||||
|
count(*)
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT value_2 FROM users_table WHERE user_id != 15 OFFSET 0
|
||||||
|
) as foo,
|
||||||
|
(
|
||||||
|
SELECT user_id FROM users_table
|
||||||
|
) as bar
|
||||||
|
WHERE foo.value_2 = bar.user_id;
|
||||||
|
|
||||||
|
|
||||||
|
-- subquery with repartition query
|
||||||
|
SET citus.enable_repartition_joins to ON;
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
count(*)
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT DISTINCT users_table.value_2 FROM users_table, events_table WHERE users_table.user_id = events_table.value_2 AND users_table.user_id < 2
|
||||||
|
) as foo,
|
||||||
|
(
|
||||||
|
SELECT user_id FROM users_table
|
||||||
|
) as bar
|
||||||
|
WHERE foo.value_2 = bar.user_id;
|
||||||
|
|
||||||
|
-- mixed of all executors (including local execution)
|
||||||
|
SELECT
|
||||||
|
count(*)
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT value_2 FROM users_table WHERE user_id = 15 OFFSET 0
|
||||||
|
) as foo,
|
||||||
|
(
|
||||||
|
SELECT user_id FROM users_table OFFSET 0
|
||||||
|
) as bar,
|
||||||
|
(
|
||||||
|
SELECT DISTINCT users_table.value_2 FROM users_table, events_table WHERE users_table.user_id = events_table.value_2 AND users_table.user_id < 2
|
||||||
|
) baz,
|
||||||
|
(
|
||||||
|
SELECT user_id FROM users_table_local WHERE user_id = 2
|
||||||
|
) baw
|
||||||
|
WHERE foo.value_2 = bar.user_id AND baz.value_2 = bar.user_id AND bar.user_id = baw.user_id;
|
||||||
|
|
||||||
|
|
||||||
|
SET citus.enable_repartition_joins to OFF;
|
||||||
|
|
||||||
|
|
||||||
|
-- final query is router
|
||||||
|
SELECT
|
||||||
|
count(*)
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT value_2 FROM users_table WHERE user_id = 1 OFFSET 0
|
||||||
|
) as foo,
|
||||||
|
(
|
||||||
|
SELECT user_id FROM users_table WHERE user_id = 2 OFFSET 0
|
||||||
|
) as bar
|
||||||
|
WHERE foo.value_2 = bar.user_id;
|
||||||
|
|
||||||
|
-- final query is real-time
|
||||||
|
SELECT
|
||||||
|
count(*)
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT value_2 FROM users_table WHERE user_id = 1 OFFSET 0
|
||||||
|
) as foo,
|
||||||
|
(
|
||||||
|
SELECT user_id FROM users_table WHERE user_id != 2
|
||||||
|
) as bar
|
||||||
|
WHERE foo.value_2 = bar.user_id;
|
||||||
|
|
||||||
|
SET client_min_messages TO DEFAULT;
|
||||||
|
|
||||||
|
DROP SCHEMA subquery_executor CASCADE;
|
||||||
|
SET search_path TO public;
|
|
@ -0,0 +1,204 @@
|
||||||
|
-- ===================================================================
|
||||||
|
-- test recursive planning functionality on local tables
|
||||||
|
-- ===================================================================
|
||||||
|
|
||||||
|
CREATE SCHEMA subquery_local_tables;
|
||||||
|
SET search_path TO subquery_local_tables, public;
|
||||||
|
|
||||||
|
|
||||||
|
CREATE TABLE users_table_local AS SELECT * FROM users_table;
|
||||||
|
CREATE TABLE events_table_local AS SELECT * FROM events_table;
|
||||||
|
|
||||||
|
SET client_min_messages TO DEBUG1;
|
||||||
|
|
||||||
|
-- foo is only on the local tables, thus can be replaced
|
||||||
|
-- bar is on the distributed tables with LIMIT, should be replaced
|
||||||
|
SELECT
|
||||||
|
foo.user_id
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
DISTINCT users_table_local.user_id
|
||||||
|
FROM
|
||||||
|
users_table_local, events_table_local
|
||||||
|
WHERE
|
||||||
|
users_table_local.user_id = events_table_local.user_id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
ORDER BY 1 DESC LIMIT 5
|
||||||
|
) as foo,
|
||||||
|
(SELECT
|
||||||
|
DISTINCT users_table.user_id
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (5,6,7,8)
|
||||||
|
ORDER BY 1 DESC LIMIT 5
|
||||||
|
) as bar
|
||||||
|
|
||||||
|
WHERE bar.user_id = foo.user_id
|
||||||
|
ORDER BY 1 DESC;
|
||||||
|
|
||||||
|
-- foo is only on the local tables, thus can be replaced
|
||||||
|
SELECT
|
||||||
|
foo.user_id
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
DISTINCT users_table_local.user_id
|
||||||
|
FROM
|
||||||
|
users_table_local, events_table_local
|
||||||
|
WHERE
|
||||||
|
users_table_local.user_id = events_table_local.user_id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
ORDER BY 1 DESC LIMIT 5
|
||||||
|
) as foo,
|
||||||
|
(SELECT
|
||||||
|
DISTINCT users_table.user_id
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (5,6,7,8)
|
||||||
|
) as bar
|
||||||
|
WHERE bar.user_id = foo.user_id
|
||||||
|
ORDER BY 1 DESC;
|
||||||
|
|
||||||
|
|
||||||
|
-- subqueries in WHERE could be replaced even if they are on the local tables
|
||||||
|
SELECT DISTINCT user_id
|
||||||
|
FROM users_table
|
||||||
|
WHERE
|
||||||
|
user_id IN (SELECT DISTINCT value_2 FROM users_table_local WHERE value_1 = 1)
|
||||||
|
ORDER BY 1 LIMIT 5;
|
||||||
|
|
||||||
|
|
||||||
|
-- subquery in FROM -> FROM -> FROM should be replaced if
|
||||||
|
-- it contains onle local tables
|
||||||
|
SELECT
|
||||||
|
DISTINCT user_id
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT users_table.user_id FROM users_table,
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
event_type, user_id
|
||||||
|
FROM
|
||||||
|
(SELECT event_type, users_table.user_id FROM users_table,
|
||||||
|
(SELECT user_id, event_type FROM events_table_local WHERE value_2 < 3 OFFSET 3) as foo
|
||||||
|
WHERE foo.user_id = users_table.user_id
|
||||||
|
) bar
|
||||||
|
|
||||||
|
) as baz
|
||||||
|
WHERE baz.user_id = users_table.user_id
|
||||||
|
|
||||||
|
) as sub1
|
||||||
|
ORDER BY 1 DESC
|
||||||
|
LIMIT 3;
|
||||||
|
|
||||||
|
|
||||||
|
-- subquery in FROM -> FROM -> WHERE -> WHERE should be replaced if
|
||||||
|
-- it contains onle local tables
|
||||||
|
-- Later the upper level query is also recursively planned due to LIMIT
|
||||||
|
SELECT user_id, array_length(events_table, 1)
|
||||||
|
FROM (
|
||||||
|
SELECT user_id, array_agg(event ORDER BY time) AS events_table
|
||||||
|
FROM (
|
||||||
|
SELECT
|
||||||
|
u.user_id, e.event_type::text AS event, e.time
|
||||||
|
FROM
|
||||||
|
users_table AS u,
|
||||||
|
events_table AS e
|
||||||
|
WHERE u.user_id = e.user_id AND
|
||||||
|
u.user_id IN
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
user_id
|
||||||
|
FROM
|
||||||
|
users_table
|
||||||
|
WHERE value_2 >= 5
|
||||||
|
AND EXISTS (SELECT user_id FROM events_table_local WHERE event_type > 1 AND event_type <= 3 AND value_3 > 1)
|
||||||
|
AND NOT EXISTS (SELECT user_id FROM events_table WHERE event_type > 3 AND event_type <= 4 AND value_3 > 1 AND user_id = users_table.user_id)
|
||||||
|
LIMIT 5
|
||||||
|
)
|
||||||
|
) t
|
||||||
|
GROUP BY user_id
|
||||||
|
) q
|
||||||
|
ORDER BY 2 DESC, 1;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- subquery (i.e., subquery_2) in WHERE->FROM should be replaced due to local tables
|
||||||
|
SELECT
|
||||||
|
user_id
|
||||||
|
FROM
|
||||||
|
users_table
|
||||||
|
WHERE
|
||||||
|
user_id IN
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
user_id
|
||||||
|
FROM (
|
||||||
|
SELECT
|
||||||
|
subquery_1.user_id, count_pay
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
(SELECT
|
||||||
|
users_table.user_id,
|
||||||
|
'action=>1' AS event,
|
||||||
|
events_table.time
|
||||||
|
FROM
|
||||||
|
users_table,
|
||||||
|
events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
users_table.user_id >= 1 AND
|
||||||
|
users_table.user_id <= 3 AND
|
||||||
|
events_table.event_type > 1 AND events_table.event_type < 3
|
||||||
|
)
|
||||||
|
UNION
|
||||||
|
(SELECT
|
||||||
|
users_table.user_id,
|
||||||
|
'action=>2' AS event,
|
||||||
|
events_table.time
|
||||||
|
FROM
|
||||||
|
users_table,
|
||||||
|
events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
users_table.user_id >= 1 AND
|
||||||
|
users_table.user_id <= 3 AND
|
||||||
|
events_table.event_type > 2 AND events_table.event_type < 4
|
||||||
|
)
|
||||||
|
) AS subquery_1
|
||||||
|
LEFT JOIN
|
||||||
|
(SELECT
|
||||||
|
user_id,
|
||||||
|
COUNT(*) AS count_pay
|
||||||
|
FROM
|
||||||
|
users_table_local
|
||||||
|
WHERE
|
||||||
|
user_id >= 1 AND
|
||||||
|
user_id <= 3 AND
|
||||||
|
users_table_local.value_1 > 3 AND users_table_local.value_1 < 5
|
||||||
|
GROUP BY
|
||||||
|
user_id
|
||||||
|
HAVING
|
||||||
|
COUNT(*) > 1
|
||||||
|
LIMIT 10
|
||||||
|
|
||||||
|
) AS subquery_2
|
||||||
|
ON
|
||||||
|
subquery_1.user_id = subquery_2.user_id
|
||||||
|
GROUP BY
|
||||||
|
subquery_1.user_id,
|
||||||
|
count_pay) AS subquery_top
|
||||||
|
GROUP BY
|
||||||
|
count_pay, user_id
|
||||||
|
)
|
||||||
|
GROUP BY user_id
|
||||||
|
HAVING count(*) > 1 AND sum(value_2) > 29
|
||||||
|
ORDER BY 1;
|
||||||
|
|
||||||
|
SET client_min_messages TO DEFAULT;
|
||||||
|
|
||||||
|
DROP SCHEMA subquery_local_tables CASCADE;
|
||||||
|
SET search_path TO public;
|
|
@ -0,0 +1,213 @@
|
||||||
|
-- ===================================================================
|
||||||
|
-- test recursive planning functionality on partitioned tables
|
||||||
|
-- ===================================================================
|
||||||
|
CREATE SCHEMA subquery_and_partitioning;
|
||||||
|
SET search_path TO subquery_and_partitioning, public;
|
||||||
|
|
||||||
|
|
||||||
|
CREATE TABLE users_table_local AS SELECT * FROM users_table;
|
||||||
|
CREATE TABLE events_table_local AS SELECT * FROM events_table;
|
||||||
|
|
||||||
|
CREATE TABLE partitioning_test(id int, value_1 int, time date) PARTITION BY RANGE (time);
|
||||||
|
|
||||||
|
-- create its partitions
|
||||||
|
CREATE TABLE partitioning_test_2017 PARTITION OF partitioning_test FOR VALUES FROM ('2017-01-01') TO ('2018-01-01');
|
||||||
|
CREATE TABLE partitioning_test_2010 PARTITION OF partitioning_test FOR VALUES FROM ('2010-01-01') TO ('2011-01-01');
|
||||||
|
|
||||||
|
-- load some data and distribute tables
|
||||||
|
INSERT INTO partitioning_test VALUES (1, 1, '2017-11-23');
|
||||||
|
INSERT INTO partitioning_test VALUES (2, 1, '2010-07-07');
|
||||||
|
|
||||||
|
INSERT INTO partitioning_test_2017 VALUES (3, 3, '2017-11-22');
|
||||||
|
INSERT INTO partitioning_test_2010 VALUES (4, 4, '2010-03-03');
|
||||||
|
|
||||||
|
-- distribute partitioned table
|
||||||
|
SET citus.shard_replication_factor TO 1;
|
||||||
|
SELECT create_distributed_table('partitioning_test', 'id');
|
||||||
|
|
||||||
|
SET client_min_messages TO DEBUG1;
|
||||||
|
|
||||||
|
-- subplan for partitioned tables
|
||||||
|
SELECT
|
||||||
|
id
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
DISTINCT partitioning_test.id
|
||||||
|
FROM
|
||||||
|
partitioning_test
|
||||||
|
LIMIT 5
|
||||||
|
) as foo
|
||||||
|
ORDER BY 1 DESC;
|
||||||
|
|
||||||
|
-- final query is router on partitioned tables
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
DISTINCT partitioning_test.id
|
||||||
|
FROM
|
||||||
|
partitioning_test
|
||||||
|
LIMIT 5
|
||||||
|
) as foo,
|
||||||
|
(SELECT
|
||||||
|
DISTINCT partitioning_test.time
|
||||||
|
FROM
|
||||||
|
partitioning_test
|
||||||
|
LIMIT 5
|
||||||
|
) as bar
|
||||||
|
WHERE foo.id = date_part('day', bar.time)
|
||||||
|
ORDER BY 2 DESC, 1;
|
||||||
|
|
||||||
|
-- final query is real-time
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
DISTINCT partitioning_test.time
|
||||||
|
FROM
|
||||||
|
partitioning_test
|
||||||
|
ORDER BY 1 DESC
|
||||||
|
LIMIT 5
|
||||||
|
) as foo,
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
DISTINCT partitioning_test.id
|
||||||
|
FROM
|
||||||
|
partitioning_test
|
||||||
|
) as bar
|
||||||
|
WHERE date_part('day', foo.time) = bar.id
|
||||||
|
ORDER BY 2 DESC, 1 DESC
|
||||||
|
LIMIT 3;
|
||||||
|
|
||||||
|
-- final query is real-time that is joined with partitioned table
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
DISTINCT partitioning_test.time
|
||||||
|
FROM
|
||||||
|
partitioning_test
|
||||||
|
ORDER BY 1 DESC
|
||||||
|
LIMIT 5
|
||||||
|
) as foo,
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
DISTINCT partitioning_test.id
|
||||||
|
FROM
|
||||||
|
partitioning_test
|
||||||
|
) as bar,
|
||||||
|
partitioning_test
|
||||||
|
WHERE date_part('day', foo.time) = bar.id AND partitioning_test.id = bar.id
|
||||||
|
ORDER BY 2 DESC, 1 DESC
|
||||||
|
LIMIT 3;
|
||||||
|
|
||||||
|
-- subquery in WHERE clause
|
||||||
|
SELECT DISTINCT id
|
||||||
|
FROM partitioning_test
|
||||||
|
WHERE
|
||||||
|
id IN (SELECT DISTINCT date_part('day', time) FROM partitioning_test);
|
||||||
|
|
||||||
|
-- repartition subquery
|
||||||
|
SET citus.enable_repartition_joins to ON;
|
||||||
|
SELECT
|
||||||
|
count(*)
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT DISTINCT p1.value_1 FROM partitioning_test as p1, partitioning_test as p2 WHERE p1.id = p2.value_1
|
||||||
|
) as foo,
|
||||||
|
(
|
||||||
|
SELECT user_id FROM users_table
|
||||||
|
) as bar
|
||||||
|
WHERE foo.value_1 = bar.user_id;
|
||||||
|
SET citus.enable_repartition_joins to OFF;
|
||||||
|
|
||||||
|
|
||||||
|
-- subquery, cte, view and non-partitioned tables
|
||||||
|
CREATE VIEW subquery_and_ctes AS
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
|
||||||
|
WITH cte AS (
|
||||||
|
WITH local_cte AS (
|
||||||
|
SELECT * FROM users_table_local
|
||||||
|
),
|
||||||
|
dist_cte AS (
|
||||||
|
SELECT
|
||||||
|
user_id
|
||||||
|
FROM
|
||||||
|
events_table,
|
||||||
|
(SELECT DISTINCT value_1 FROM partitioning_test OFFSET 0) as foo
|
||||||
|
WHERE
|
||||||
|
events_table.user_id = foo.value_1 AND
|
||||||
|
events_table.user_id IN (SELECT DISTINCT value_1 FROM users_table ORDER BY 1 LIMIT 3)
|
||||||
|
)
|
||||||
|
SELECT dist_cte.user_id FROM local_cte join dist_cte on dist_cte.user_id=local_cte.user_id
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
count(*) as cnt
|
||||||
|
FROM
|
||||||
|
cte,
|
||||||
|
(SELECT
|
||||||
|
DISTINCT events_table.user_id
|
||||||
|
FROM
|
||||||
|
partitioning_test, events_table
|
||||||
|
WHERE
|
||||||
|
events_table.user_id = partitioning_test.id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
ORDER BY 1 DESC LIMIT 5
|
||||||
|
) as foo
|
||||||
|
WHERE foo.user_id = cte.user_id
|
||||||
|
|
||||||
|
) as foo, users_table WHERE foo.cnt > users_table.value_2;
|
||||||
|
|
||||||
|
SELECT * FROM subquery_and_ctes
|
||||||
|
ORDER BY 3 DESC, 1 DESC, 2 DESC, 4 DESC
|
||||||
|
LIMIT 5;
|
||||||
|
|
||||||
|
-- deep subquery, partitioned and non-partitioned tables together
|
||||||
|
SELECT count(*)
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT avg(min) FROM
|
||||||
|
(
|
||||||
|
SELECT min(partitioning_test.value_1) FROM
|
||||||
|
(
|
||||||
|
SELECT avg(event_type) as avg_ev_type FROM
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
max(value_1) as mx_val_1
|
||||||
|
FROM (
|
||||||
|
SELECT
|
||||||
|
avg(event_type) as avg
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
cnt
|
||||||
|
FROM
|
||||||
|
(SELECT count(*) as cnt, value_1 FROM partitioning_test GROUP BY value_1) as level_1, users_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = level_1.cnt
|
||||||
|
) as level_2, events_table
|
||||||
|
WHERE events_table.user_id = level_2.cnt
|
||||||
|
GROUP BY level_2.cnt
|
||||||
|
) as level_3, users_table
|
||||||
|
WHERE user_id = level_3.avg
|
||||||
|
GROUP BY level_3.avg
|
||||||
|
) as level_4, events_table
|
||||||
|
WHERE level_4.mx_val_1 = events_table.user_id
|
||||||
|
GROUP BY level_4.mx_val_1
|
||||||
|
) as level_5, partitioning_test
|
||||||
|
WHERE
|
||||||
|
level_5.avg_ev_type = partitioning_test.id
|
||||||
|
GROUP BY
|
||||||
|
level_5.avg_ev_type
|
||||||
|
) as level_6, users_table WHERE users_table.user_id = level_6.min
|
||||||
|
GROUP BY users_table.value_1
|
||||||
|
) as bar;
|
||||||
|
|
||||||
|
SET client_min_messages TO DEFAULT;
|
||||||
|
|
||||||
|
DROP SCHEMA subquery_and_partitioning CASCADE;
|
||||||
|
SET search_path TO public;
|
|
@ -0,0 +1,89 @@
|
||||||
|
-- ===================================================================
|
||||||
|
-- test recursive planning functionality on prepared statements
|
||||||
|
-- ===================================================================
|
||||||
|
CREATE SCHEMA subquery_prepared_statements;
|
||||||
|
SET search_path TO subquery_prepared_statements, public;
|
||||||
|
|
||||||
|
CREATE TYPE xy AS (x int, y int);
|
||||||
|
|
||||||
|
SELECT run_command_on_workers('CREATE SCHEMA subquery_prepared_statements');
|
||||||
|
SELECT run_command_on_workers('CREATE TYPE subquery_prepared_statements.xy AS (x int, y int)');
|
||||||
|
|
||||||
|
SET client_min_messages TO DEBUG1;
|
||||||
|
|
||||||
|
PREPARE subquery_prepare_without_param AS
|
||||||
|
SELECT
|
||||||
|
DISTINCT values_of_subquery
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
DISTINCT (users_table.user_id, events_table.event_type)::xy as values_of_subquery
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
ORDER BY 1 DESC LIMIT 5
|
||||||
|
) as foo
|
||||||
|
ORDER BY 1 DESC;
|
||||||
|
|
||||||
|
PREPARE subquery_prepare_param_on_partkey(int) AS
|
||||||
|
SELECT
|
||||||
|
DISTINCT values_of_subquery
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
DISTINCT (users_table.user_id, events_table.event_type)::xy as values_of_subquery
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
(users_table.user_id = $1 OR users_table.user_id = 2) AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
ORDER BY 1 DESC LIMIT 5
|
||||||
|
) as foo
|
||||||
|
ORDER BY 1 DESC;
|
||||||
|
|
||||||
|
PREPARE subquery_prepare_param_non_partkey(int) AS
|
||||||
|
SELECT
|
||||||
|
DISTINCT values_of_subquery
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
DISTINCT (users_table.user_id, events_table.event_type)::xy as values_of_subquery
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type = $1
|
||||||
|
ORDER BY 1 DESC LIMIT 5
|
||||||
|
) as foo
|
||||||
|
ORDER BY 1 DESC;
|
||||||
|
|
||||||
|
-- execute each test with 6 times
|
||||||
|
|
||||||
|
EXECUTE subquery_prepare_without_param;
|
||||||
|
EXECUTE subquery_prepare_without_param;
|
||||||
|
EXECUTE subquery_prepare_without_param;
|
||||||
|
EXECUTE subquery_prepare_without_param;
|
||||||
|
EXECUTE subquery_prepare_without_param;
|
||||||
|
EXECUTE subquery_prepare_without_param;
|
||||||
|
EXECUTE subquery_prepare_without_param;
|
||||||
|
|
||||||
|
|
||||||
|
EXECUTE subquery_prepare_param_on_partkey(1);
|
||||||
|
EXECUTE subquery_prepare_param_on_partkey(1);
|
||||||
|
EXECUTE subquery_prepare_param_on_partkey(1);
|
||||||
|
EXECUTE subquery_prepare_param_on_partkey(1);
|
||||||
|
EXECUTE subquery_prepare_param_on_partkey(1);
|
||||||
|
EXECUTE subquery_prepare_param_on_partkey(1);
|
||||||
|
|
||||||
|
EXECUTE subquery_prepare_param_non_partkey(1);
|
||||||
|
EXECUTE subquery_prepare_param_non_partkey(1);
|
||||||
|
EXECUTE subquery_prepare_param_non_partkey(1);
|
||||||
|
EXECUTE subquery_prepare_param_non_partkey(1);
|
||||||
|
EXECUTE subquery_prepare_param_non_partkey(1);
|
||||||
|
EXECUTE subquery_prepare_param_non_partkey(1);
|
||||||
|
|
||||||
|
|
||||||
|
SET client_min_messages TO DEFAULT;
|
||||||
|
|
||||||
|
DROP SCHEMA subquery_prepared_statements CASCADE;
|
||||||
|
SET search_path TO public;
|
|
@ -0,0 +1,427 @@
|
||||||
|
-- ===================================================================
|
||||||
|
-- test recursive planning functionality on views
|
||||||
|
-- ===================================================================
|
||||||
|
|
||||||
|
CREATE SCHEMA subquery_view;
|
||||||
|
SET search_path TO subquery_view, public;
|
||||||
|
|
||||||
|
|
||||||
|
CREATE TABLE users_table_local AS SELECT * FROM users_table;
|
||||||
|
CREATE TABLE events_table_local AS SELECT * FROM events_table;
|
||||||
|
|
||||||
|
SET client_min_messages TO DEBUG1;
|
||||||
|
|
||||||
|
CREATE VIEW view_without_subquery AS
|
||||||
|
SELECT
|
||||||
|
DISTINCT users_table.value_1
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
ORDER BY 1 DESC;
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
view_without_subquery
|
||||||
|
ORDER BY 1 DESC LIMIT 5;
|
||||||
|
|
||||||
|
CREATE VIEW view_without_subquery_second AS
|
||||||
|
SELECT
|
||||||
|
DISTINCT users_table.user_id
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
ORDER BY 1 DESC
|
||||||
|
LIMIT 5;
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
view_without_subquery_second
|
||||||
|
ORDER BY 1;
|
||||||
|
|
||||||
|
-- subqueries in FROM clause with LIMIT should be recursively planned
|
||||||
|
CREATE VIEW subquery_limit AS
|
||||||
|
SELECT
|
||||||
|
user_id
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
DISTINCT users_table.user_id
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
ORDER BY 1 DESC LIMIT 5
|
||||||
|
) as foo
|
||||||
|
ORDER BY 1 DESC;
|
||||||
|
|
||||||
|
SELECT * FROM subquery_limit ORDER BY 1 DESC;
|
||||||
|
|
||||||
|
-- subqueries in FROM clause with GROUP BY non-distribution column should be recursively planned
|
||||||
|
CREATE VIEW subquery_non_p_key_group_by AS
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
DISTINCT users_table.value_1
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
ORDER BY 1
|
||||||
|
) as foo
|
||||||
|
ORDER BY 1 DESC;
|
||||||
|
|
||||||
|
SELECT * FROM subquery_non_p_key_group_by ORDER BY 1 DESC;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
CREATE VIEW final_query_router AS
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
users_table.value_2
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
GROUP BY users_table.value_2
|
||||||
|
ORDER BY 1 DESC
|
||||||
|
) as foo,
|
||||||
|
(SELECT
|
||||||
|
users_table.value_3
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (5,6,7,8)
|
||||||
|
GROUP BY users_table.value_3
|
||||||
|
ORDER BY 1 DESC
|
||||||
|
) as bar
|
||||||
|
WHERE foo.value_2 = bar.value_3
|
||||||
|
ORDER BY 2 DESC, 1;
|
||||||
|
|
||||||
|
SELECT * FROM final_query_router ORDER BY 1;
|
||||||
|
|
||||||
|
CREATE VIEW final_query_realtime AS
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
users_table.value_2
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
GROUP BY users_table.value_2
|
||||||
|
ORDER BY 1 DESC
|
||||||
|
) as foo,
|
||||||
|
(SELECT
|
||||||
|
users_table.user_id
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (5,6,7,8)
|
||||||
|
ORDER BY 1 DESC
|
||||||
|
) as bar
|
||||||
|
WHERE foo.value_2 = bar.user_id
|
||||||
|
ORDER BY 2 DESC, 1 DESC
|
||||||
|
LIMIT 3;
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
DISTINCT ON (users_table.value_2) users_table.value_2, time, value_3
|
||||||
|
FROM
|
||||||
|
final_query_realtime, users_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = final_query_realtime.user_id
|
||||||
|
ORDER BY 1 DESC, 2 DESC, 3 DESC
|
||||||
|
LIMIT 3;
|
||||||
|
|
||||||
|
|
||||||
|
CREATE VIEW subquery_in_where AS
|
||||||
|
SELECT DISTINCT user_id
|
||||||
|
FROM users_table
|
||||||
|
WHERE
|
||||||
|
user_id IN (SELECT DISTINCT value_2 FROM users_table WHERE value_1 >= 1 AND value_1 <= 20 ORDER BY 1 LIMIT 5);
|
||||||
|
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
subquery_in_where
|
||||||
|
ORDER BY 1 DESC;
|
||||||
|
|
||||||
|
|
||||||
|
-- subquery in FROM -> FROM -> WHERE should be replaced due to LIMIT
|
||||||
|
CREATE VIEW subquery_from_from_where AS
|
||||||
|
SELECT user_id, array_length(events_table, 1)
|
||||||
|
FROM (
|
||||||
|
SELECT user_id, array_agg(event ORDER BY time) AS events_table
|
||||||
|
FROM (
|
||||||
|
SELECT
|
||||||
|
u.user_id, e.event_type::text AS event, e.time
|
||||||
|
FROM
|
||||||
|
users_table AS u,
|
||||||
|
events_table AS e
|
||||||
|
WHERE u.user_id = e.user_id AND
|
||||||
|
u.user_id IN
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
user_id
|
||||||
|
FROM
|
||||||
|
users_table
|
||||||
|
WHERE value_2 >= 5
|
||||||
|
AND EXISTS (SELECT user_id FROM events_table WHERE event_type > 1 AND event_type <= 3 AND value_3 > 1 AND user_id = users_table.user_id)
|
||||||
|
AND NOT EXISTS (SELECT user_id FROM events_table WHERE event_type > 3 AND event_type <= 4 AND value_3 > 1 AND user_id = users_table.user_id)
|
||||||
|
LIMIT 5
|
||||||
|
)
|
||||||
|
) t
|
||||||
|
GROUP BY user_id
|
||||||
|
) q;
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
subquery_from_from_where
|
||||||
|
ORDER BY
|
||||||
|
2 DESC, 1;
|
||||||
|
|
||||||
|
|
||||||
|
-- subquery in FROM -> FROM -> FROM should be replaced if
|
||||||
|
-- it contains onle local tables
|
||||||
|
CREATE VIEW subquery_from_from_where_local_table AS
|
||||||
|
SELECT
|
||||||
|
DISTINCT user_id
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT users_table.user_id FROM users_table,
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
event_type, user_id
|
||||||
|
FROM
|
||||||
|
(SELECT event_type, users_table.user_id FROM users_table,
|
||||||
|
(SELECT user_id, event_type FROM events_table_local WHERE value_2 < 3 OFFSET 3) as foo
|
||||||
|
WHERE foo.user_id = users_table.user_id
|
||||||
|
) bar
|
||||||
|
|
||||||
|
) as baz
|
||||||
|
WHERE baz.user_id = users_table.user_id
|
||||||
|
|
||||||
|
) as sub1;
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
subquery_from_from_where
|
||||||
|
ORDER BY 1 DESC
|
||||||
|
LIMIT 3;
|
||||||
|
|
||||||
|
SET citus.enable_repartition_joins to ON;
|
||||||
|
|
||||||
|
CREATE VIEW repartition_view AS
|
||||||
|
SELECT
|
||||||
|
count(*)
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT DISTINCT users_table.value_2 FROM users_table, events_table WHERE users_table.user_id = events_table.value_2 AND users_table.user_id < 2
|
||||||
|
) as foo,
|
||||||
|
(
|
||||||
|
SELECT user_id FROM users_table
|
||||||
|
) as bar
|
||||||
|
WHERE foo.value_2 = bar.user_id;
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
repartition_view;
|
||||||
|
|
||||||
|
CREATE VIEW all_executors_view AS
|
||||||
|
SELECT
|
||||||
|
count(*)
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT value_2 FROM users_table WHERE user_id = 15 OFFSET 0
|
||||||
|
) as foo,
|
||||||
|
(
|
||||||
|
SELECT user_id FROM users_table OFFSET 0
|
||||||
|
) as bar,
|
||||||
|
(
|
||||||
|
SELECT DISTINCT users_table.value_2 FROM users_table, events_table WHERE users_table.user_id = events_table.value_2 AND users_table.user_id < 2
|
||||||
|
) baz,
|
||||||
|
(
|
||||||
|
SELECT user_id FROM users_table_local WHERE user_id = 2
|
||||||
|
) baw
|
||||||
|
WHERE foo.value_2 = bar.user_id AND baz.value_2 = bar.user_id AND bar.user_id = baw.user_id;
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
all_executors_view;
|
||||||
|
|
||||||
|
SET citus.enable_repartition_joins to OFF;
|
||||||
|
|
||||||
|
|
||||||
|
-- the same query, but this time the CTEs also live inside a subquery
|
||||||
|
CREATE VIEW subquery_and_ctes AS
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
|
||||||
|
WITH cte AS (
|
||||||
|
WITH local_cte AS (
|
||||||
|
SELECT * FROM users_table_local
|
||||||
|
),
|
||||||
|
dist_cte AS (
|
||||||
|
SELECT
|
||||||
|
user_id
|
||||||
|
FROM
|
||||||
|
events_table,
|
||||||
|
(SELECT DISTINCT value_2 FROM users_table OFFSET 0) as foo
|
||||||
|
WHERE
|
||||||
|
events_table.user_id = foo.value_2 AND
|
||||||
|
events_table.user_id IN (SELECT DISTINCT value_1 FROM users_table ORDER BY 1 LIMIT 3)
|
||||||
|
)
|
||||||
|
SELECT dist_cte.user_id FROM local_cte join dist_cte on dist_cte.user_id=local_cte.user_id
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
count(*) as cnt
|
||||||
|
FROM
|
||||||
|
cte,
|
||||||
|
(SELECT
|
||||||
|
DISTINCT users_table.user_id
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
ORDER BY 1 DESC LIMIT 5
|
||||||
|
) as foo
|
||||||
|
WHERE foo.user_id = cte.user_id
|
||||||
|
|
||||||
|
) as foo, users_table WHERE foo.cnt > users_table.value_2;
|
||||||
|
|
||||||
|
SELECT * FROM subquery_and_ctes
|
||||||
|
ORDER BY 3 DESC, 1 DESC, 2 DESC, 4 DESC
|
||||||
|
LIMIT 5;
|
||||||
|
|
||||||
|
|
||||||
|
CREATE VIEW subquery_and_ctes_second AS
|
||||||
|
SELECT time, event_type, value_2, value_3 FROM
|
||||||
|
(
|
||||||
|
WITH cte AS (
|
||||||
|
WITH local_cte AS (
|
||||||
|
SELECT * FROM users_table_local
|
||||||
|
),
|
||||||
|
dist_cte AS (
|
||||||
|
SELECT user_id FROM events_table
|
||||||
|
)
|
||||||
|
SELECT dist_cte.user_id FROM local_cte join dist_cte on dist_cte.user_id=local_cte.user_id
|
||||||
|
)
|
||||||
|
SELECT DISTINCT cte.user_id
|
||||||
|
FROM users_table, cte
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = cte.user_id AND
|
||||||
|
users_table.user_id IN
|
||||||
|
(WITH cte_in_where AS (SELECT DISTINCT value_2 FROM users_table WHERE value_1 >= 1 AND value_1 <= 20 ORDER BY 1 LIMIT 5) SELECT * FROM cte_in_where)
|
||||||
|
ORDER BY 1 DESC
|
||||||
|
) as foo,
|
||||||
|
events_table
|
||||||
|
WHERE
|
||||||
|
foo.user_id = events_table.value_2;
|
||||||
|
|
||||||
|
|
||||||
|
SELECT * FROM subquery_and_ctes_second
|
||||||
|
ORDER BY 3 DESC, 2 DESC, 1 DESC
|
||||||
|
LIMIT 5;
|
||||||
|
|
||||||
|
CREATE VIEW deep_subquery AS
|
||||||
|
SELECT count(*)
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT avg(min) FROM
|
||||||
|
(
|
||||||
|
SELECT min(users_table.value_1) FROM
|
||||||
|
(
|
||||||
|
SELECT avg(event_type) as avg_ev_type FROM
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
max(value_1) as mx_val_1
|
||||||
|
FROM (
|
||||||
|
SELECT
|
||||||
|
avg(event_type) as avg
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
cnt
|
||||||
|
FROM
|
||||||
|
(SELECT count(*) as cnt, value_2 FROM users_table GROUP BY value_2) as level_1, users_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = level_1.cnt
|
||||||
|
) as level_2, events_table
|
||||||
|
WHERE events_table.user_id = level_2.cnt
|
||||||
|
GROUP BY level_2.cnt
|
||||||
|
) as level_3, users_table
|
||||||
|
WHERE user_id = level_3.avg
|
||||||
|
GROUP BY level_3.avg
|
||||||
|
) as level_4, events_table
|
||||||
|
WHERE level_4.mx_val_1 = events_table.user_id
|
||||||
|
GROUP BY level_4.mx_val_1
|
||||||
|
) as level_5, users_table
|
||||||
|
WHERE
|
||||||
|
level_5.avg_ev_type = users_table.user_id
|
||||||
|
GROUP BY
|
||||||
|
level_5.avg_ev_type
|
||||||
|
) as level_6, users_table WHERE users_table.user_id = level_6.min
|
||||||
|
GROUP BY users_table.value_1
|
||||||
|
) as bar;
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
deep_subquery;
|
||||||
|
|
||||||
|
|
||||||
|
CREATE VIEW result_of_view_is_also_recursively_planned AS
|
||||||
|
SELECT
|
||||||
|
user_id
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
DISTINCT users_table.user_id
|
||||||
|
FROM
|
||||||
|
users_table, events_table
|
||||||
|
WHERE
|
||||||
|
users_table.user_id = events_table.user_id AND
|
||||||
|
event_type IN (1,2,3,4)
|
||||||
|
ORDER BY 1 DESC LIMIT 5
|
||||||
|
) as foo
|
||||||
|
ORDER BY 1 DESC;
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
(SELECT
|
||||||
|
*
|
||||||
|
FROM
|
||||||
|
result_of_view_is_also_recursively_planned, events_table
|
||||||
|
WHERE
|
||||||
|
events_table.value_2 = result_of_view_is_also_recursively_planned.user_id
|
||||||
|
ORDER BY time DESC
|
||||||
|
LIMIT 5
|
||||||
|
OFFSET 4
|
||||||
|
|
||||||
|
) as foo
|
||||||
|
ORDER BY time DESC LIMIT 5;
|
||||||
|
|
||||||
|
SET client_min_messages TO DEFAULT;
|
||||||
|
|
||||||
|
DROP SCHEMA subquery_view CASCADE;
|
||||||
|
SET search_path TO public;
|
|
@ -54,13 +54,13 @@ ORDER BY
|
||||||
LIMIT
|
LIMIT
|
||||||
5;
|
5;
|
||||||
|
|
||||||
-- CTE in subquery errors out
|
-- CTE in subquery recursively planned
|
||||||
SELECT user_id FROM (
|
SELECT user_id FROM (
|
||||||
WITH cte AS (
|
WITH cte AS (
|
||||||
SELECT user_id, value_2 from users_table WHERE user_id IN (1, 2) ORDER BY 2 LIMIT 5
|
SELECT user_id, value_2 from users_table WHERE user_id IN (1, 2) ORDER BY 2 LIMIT 5
|
||||||
)
|
)
|
||||||
SELECT user_id FROM cte WHERE value_2 > 0
|
SELECT user_id FROM cte WHERE value_2 > 0
|
||||||
) a;
|
) a ORDER BY 1 LIMIT 3;
|
||||||
|
|
||||||
-- CTE outside of FROM/WHERE errors out
|
-- CTE outside of FROM/WHERE errors out
|
||||||
WITH cte AS (
|
WITH cte AS (
|
||||||
|
@ -458,14 +458,14 @@ WITH cte_user AS (
|
||||||
)
|
)
|
||||||
SELECT user_id, sum(value_2) FROM cte_user GROUP BY 1 ORDER BY 1, 2;
|
SELECT user_id, sum(value_2) FROM cte_user GROUP BY 1 ORDER BY 1, 2;
|
||||||
|
|
||||||
SELECT * FROM cte_view;
|
SELECT * FROM cte_view ORDER BY 1, 2 LIMIT 5;
|
||||||
|
|
||||||
|
|
||||||
WITH cte_user_with_view AS
|
WITH cte_user_with_view AS
|
||||||
(
|
(
|
||||||
SELECT * FROM cte_view WHERE user_id < 3
|
SELECT * FROM cte_view WHERE user_id < 3
|
||||||
)
|
)
|
||||||
SELECT user_id, value_1 FROM cte_user_with_view ORDER BY 1, 2 LIMIT 10 OFFSET 3;
|
SELECT user_id, value_1 FROM cte_user_with_view ORDER BY 1, 2 LIMIT 10 OFFSET 2;
|
||||||
|
|
||||||
DROP VIEW basic_view;
|
DROP VIEW basic_view;
|
||||||
DROP VIEW cte_view;
|
DROP VIEW cte_view;
|
||||||
|
|
|
@ -66,6 +66,7 @@ ORDER BY
|
||||||
|
|
||||||
-- Subqueries in WHERE and FROM are mixed
|
-- Subqueries in WHERE and FROM are mixed
|
||||||
-- In this query, only subquery in WHERE is not a colocated join
|
-- In this query, only subquery in WHERE is not a colocated join
|
||||||
|
-- but we're able to recursively plan that as well
|
||||||
WITH users_events AS (
|
WITH users_events AS (
|
||||||
WITH colocated_join AS (
|
WITH colocated_join AS (
|
||||||
SELECT
|
SELECT
|
||||||
|
@ -117,13 +118,13 @@ WITH users_events AS (
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
SELECT
|
SELECT
|
||||||
*
|
DISTINCT uid
|
||||||
FROM
|
FROM
|
||||||
users_events
|
users_events
|
||||||
ORDER BY
|
ORDER BY
|
||||||
1, 2
|
1 DESC
|
||||||
LIMIT
|
LIMIT
|
||||||
20;
|
5;
|
||||||
|
|
||||||
-- cte LEFT JOIN distributed_table should error out
|
-- cte LEFT JOIN distributed_table should error out
|
||||||
WITH cte AS (
|
WITH cte AS (
|
||||||
|
|
|
@ -110,6 +110,10 @@ WHERE
|
||||||
);
|
);
|
||||||
|
|
||||||
-- CTE in WHERE basic
|
-- CTE in WHERE basic
|
||||||
|
-- this is a tricky query that hits an aggresive
|
||||||
|
-- check in subquery puwhdown after the recursive planning
|
||||||
|
-- where LIMIT should be allowed
|
||||||
|
-- if the query contains only intermediate results
|
||||||
SELECT
|
SELECT
|
||||||
count(*)
|
count(*)
|
||||||
FROM
|
FROM
|
||||||
|
@ -131,6 +135,10 @@ IN
|
||||||
);
|
);
|
||||||
|
|
||||||
-- CTE with non-colocated join in WHERE
|
-- CTE with non-colocated join in WHERE
|
||||||
|
-- this is a tricky query that hits an aggresive
|
||||||
|
-- check in subquery puwhdown after the recursive planning
|
||||||
|
-- where LIMIT should be allowed
|
||||||
|
-- if the query contains only intermediate results
|
||||||
SELECT
|
SELECT
|
||||||
count(*)
|
count(*)
|
||||||
FROM
|
FROM
|
||||||
|
|
Loading…
Reference in New Issue