From 7aa718b2f71c7d14150b3c8ab294352c08398c2c Mon Sep 17 00:00:00 2001 From: Onder Kalaci Date: Wed, 28 Nov 2018 19:33:58 +0300 Subject: [PATCH] respect the regression tests for recursively plan inner parts of recurring tuple joins --- .../expected/multi_dropped_column_aliases.out | 11 +- .../expected/multi_shard_update_delete.out | 12 +- ...ulti_subquery_complex_reference_clause.out | 250 +++++++++++++----- ...lti_subquery_in_where_reference_clause.out | 57 ++-- src/test/regress/expected/multi_view.out | 2 +- .../set_operation_and_local_tables.out | 40 +-- src/test/regress/expected/set_operations.out | 7 +- .../expected/subqueries_not_supported.out | 2 + .../regress/expected/subquery_in_where.out | 25 +- .../input/multi_outer_join_reference.source | 18 +- .../output/multi_outer_join_reference.source | 48 +++- .../sql/multi_dropped_column_aliases.sql | 10 +- ...ulti_subquery_complex_reference_clause.sql | 64 +++-- ...lti_subquery_in_where_reference_clause.sql | 23 +- 14 files changed, 408 insertions(+), 161 deletions(-) diff --git a/src/test/regress/expected/multi_dropped_column_aliases.out b/src/test/regress/expected/multi_dropped_column_aliases.out index 6dc77a058..0fb185df6 100644 --- a/src/test/regress/expected/multi_dropped_column_aliases.out +++ b/src/test/regress/expected/multi_dropped_column_aliases.out @@ -54,9 +54,8 @@ SELECT count(*) FROM customer, orders WHERE c_custkey = o_custkey; -- Test joinExpr aliases by performing an outer-join. This code path is -- currently not exercised, but we are adding this test to catch this bug when -- we start supporting outer joins. -SELECT c_custkey -FROM (customer LEFT OUTER JOIN orders ON (c_custkey = o_custkey)) AS - test(c_custkey, c_nationkey) - INNER JOIN lineitem ON (test.c_custkey = l_orderkey) -LIMIT 10; -ERROR: complex joins are only supported when all distributed tables are joined on their distribution columns with equal operator +--SELECT c_custkey +--FROM (customer LEFT OUTER JOIN orders ON (c_custkey = o_custkey)) AS + -- test(c_custkey, c_nationkey) + -- INNER JOIN lineitem ON (test.c_custkey = l_orderkey) +--LIMIT 10; diff --git a/src/test/regress/expected/multi_shard_update_delete.out b/src/test/regress/expected/multi_shard_update_delete.out index c4188e65b..6cf19f602 100644 --- a/src/test/regress/expected/multi_shard_update_delete.out +++ b/src/test/regress/expected/multi_shard_update_delete.out @@ -686,8 +686,16 @@ WHERE user_id IN (SELECT DISTINCT e2.user_id FROM users_reference_copy_table LEFT JOIN users_test_table e2 ON (e2.user_id = users_reference_copy_table.value_1)) RETURNING *; -ERROR: cannot pushdown the subquery -DETAIL: There exist a reference table in the outer part of the outer join + user_id | value_1 | value_2 | value_3 +---------+---------+---------+--------- + 5 | 4 | 1 | 0 + 5 | 4 | 1 | 0 + 5 | 4 | 1 | 0 + 16 | 4 | | 0 + 6 | 4 | 11 | 0 + 6 | 4 | 15 | 0 +(6 rows) + -- Volatile functions are also not supported UPDATE users_test_table SET value_2 = 5 diff --git a/src/test/regress/expected/multi_subquery_complex_reference_clause.out b/src/test/regress/expected/multi_subquery_complex_reference_clause.out index 4d64bdb4a..e7afa54e9 100644 --- a/src/test/regress/expected/multi_subquery_complex_reference_clause.out +++ b/src/test/regress/expected/multi_subquery_complex_reference_clause.out @@ -77,12 +77,27 @@ ORDER BY 1; 7 (10 rows) --- Shouldn't work, reference table at the outer side is not allowed +SET client_min_messages TO DEBUG; +-- Should work because we can recursively plan the distributed relation on the +-- inner part of the outer join SELECT * FROM - (SELECT random() FROM users_ref_test_table LEFT JOIN user_buy_test_table - ON users_ref_test_table.id = user_buy_test_table.user_id) subquery_1; -ERROR: cannot pushdown the subquery -DETAIL: There exist a reference table in the outer part of the outer join + (SELECT users_ref_test_table.id FROM users_ref_test_table LEFT JOIN user_buy_test_table + ON users_ref_test_table.id = user_buy_test_table.user_id) subquery_1 ORDER BY 1 DESC; +DEBUG: generating subplan 12_1 for subquery SELECT user_id, NULL::integer AS item_id, NULL::integer AS buy_count FROM public.user_buy_test_table WHERE true +DEBUG: Plan 12 query after replacing subqueries and CTEs: SELECT id FROM (SELECT users_ref_test_table.id FROM (public.users_ref_test_table LEFT JOIN (SELECT intermediate_result.user_id, intermediate_result.item_id, intermediate_result.buy_count FROM read_intermediate_result('12_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer, item_id integer, buy_count integer)) user_buy_test_table(user_id, item_id, buy_count) ON ((users_ref_test_table.id OPERATOR(pg_catalog.=) user_buy_test_table.user_id)))) subquery_1 ORDER BY id DESC +DEBUG: Creating router plan +DEBUG: Plan is router executable + id +---- + 6 + 5 + 4 + 3 + 2 + 1 +(6 rows) + +RESET client_min_messages; -- Should work, reference table at the inner side is allowed SELECT count(*) FROM (SELECT random() FROM users_ref_test_table RIGHT JOIN user_buy_test_table @@ -92,12 +107,22 @@ SELECT count(*) FROM 4 (1 row) --- Shouldn't work, reference table at the outer side is not allowed -SELECT * FROM +SET client_min_messages TO DEBUG; +-- Should work because we can recursively plan the distributed relation on the +-- inner part of the outer join +SELECT count(*) FROM (SELECT random() FROM user_buy_test_table RIGHT JOIN users_ref_test_table ON user_buy_test_table.user_id = users_ref_test_table.id) subquery_1; -ERROR: cannot pushdown the subquery -DETAIL: There exist a reference table in the outer part of the outer join +DEBUG: generating subplan 15_1 for subquery SELECT user_id, NULL::integer AS item_id, NULL::integer AS buy_count FROM public.user_buy_test_table WHERE true +DEBUG: Plan 15 query after replacing subqueries and CTEs: SELECT count(*) AS count FROM (SELECT random() AS random FROM ((SELECT intermediate_result.user_id, intermediate_result.item_id, intermediate_result.buy_count FROM read_intermediate_result('15_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer, item_id integer, buy_count integer)) user_buy_test_table(user_id, item_id, buy_count) RIGHT JOIN public.users_ref_test_table ON ((user_buy_test_table.user_id OPERATOR(pg_catalog.=) users_ref_test_table.id)))) subquery_1 +DEBUG: Creating router plan +DEBUG: Plan is router executable + count +------- + 6 +(1 row) + +RESET client_min_messages; -- Equi join test with reference table on non-partition keys SELECT count(*) FROM (SELECT random() FROM user_buy_test_table JOIN users_ref_test_table @@ -266,23 +291,40 @@ ON user_buy_test_table.item_id = users_ref_test_table.id; 4 (1 row) --- table function cannot be the outer relationship in an outer join +SET client_min_messages TO DEBUG; +-- table function can be the outer relationship in an outer join +-- since the inner side is recursively planned SELECT count(*) FROM (SELECT random() FROM user_buy_test_table RIGHT JOIN generate_series(1,10) AS users_ref_test_table(id) ON user_buy_test_table.item_id > users_ref_test_table.id) subquery_1; -ERROR: cannot pushdown the subquery -DETAIL: There exist a table function in the outer part of the outer join +DEBUG: generating subplan 30_1 for subquery SELECT NULL::integer AS user_id, item_id, NULL::integer AS buy_count FROM public.user_buy_test_table WHERE true +DEBUG: Plan 30 query after replacing subqueries and CTEs: SELECT count(*) AS count FROM (SELECT random() AS random FROM ((SELECT intermediate_result.user_id, intermediate_result.item_id, intermediate_result.buy_count FROM read_intermediate_result('30_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer, item_id integer, buy_count integer)) user_buy_test_table(user_id, item_id, buy_count) RIGHT JOIN (SELECT users_ref_test_table_1.id FROM generate_series(1, 10) users_ref_test_table_1(id)) users_ref_test_table(id) ON ((user_buy_test_table.item_id OPERATOR(pg_catalog.>) users_ref_test_table.id)))) subquery_1 +DEBUG: Creating router plan +DEBUG: Plan is router executable + count +------- + 16 +(1 row) + SELECT count(*) FROM user_buy_test_table RIGHT JOIN (SELECT * FROM generate_series(1,10) id) users_ref_test_table ON user_buy_test_table.item_id = users_ref_test_table.id; -ERROR: cannot pushdown the subquery -DETAIL: There exist a table function in the outer part of the outer join +DEBUG: generating subplan 32_1 for subquery SELECT NULL::integer AS user_id, item_id, NULL::integer AS buy_count FROM public.user_buy_test_table WHERE true +DEBUG: Plan 32 query after replacing subqueries and CTEs: SELECT count(*) AS count FROM ((SELECT intermediate_result.user_id, intermediate_result.item_id, intermediate_result.buy_count FROM read_intermediate_result('32_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer, item_id integer, buy_count integer)) user_buy_test_table(user_id, item_id, buy_count) RIGHT JOIN (SELECT id.id FROM generate_series(1, 10) id(id)) users_ref_test_table ON ((user_buy_test_table.item_id OPERATOR(pg_catalog.=) users_ref_test_table.id))) +DEBUG: Creating router plan +DEBUG: Plan is router executable + count +------- + 10 +(1 row) + +RESET client_min_messages; -- volatile functions can be used as table expressions through recursive planning SET client_min_messages TO DEBUG; SELECT count(*) FROM (SELECT random() FROM user_buy_test_table JOIN random() AS users_ref_test_table(id) ON user_buy_test_table.item_id > users_ref_test_table.id) subquery_1; -DEBUG: generating subplan 30_1 for subquery SELECT id FROM random() users_ref_test_table(id) -DEBUG: Plan 30 query after replacing subqueries and CTEs: SELECT count(*) AS count FROM (SELECT random() AS random FROM (public.user_buy_test_table JOIN (SELECT intermediate_result.id FROM read_intermediate_result('30_1'::text, 'binary'::citus_copy_format) intermediate_result(id double precision)) users_ref_test_table(id) ON (((user_buy_test_table.item_id)::double precision OPERATOR(pg_catalog.>) users_ref_test_table.id)))) subquery_1 +DEBUG: generating subplan 34_1 for subquery SELECT id FROM random() users_ref_test_table(id) +DEBUG: Plan 34 query after replacing subqueries and CTEs: SELECT count(*) AS count FROM (SELECT random() AS random FROM (public.user_buy_test_table JOIN (SELECT intermediate_result.id FROM read_intermediate_result('34_1'::text, 'binary'::citus_copy_format) intermediate_result(id double precision)) users_ref_test_table(id) ON (((user_buy_test_table.item_id)::double precision OPERATOR(pg_catalog.>) users_ref_test_table.id)))) subquery_1 count ------- 4 @@ -293,8 +335,8 @@ SELECT count(*) FROM (SELECT item_id FROM user_buy_test_table JOIN generate_series(random()::int,10) AS users_ref_test_table(id) ON user_buy_test_table.item_id > users_ref_test_table.id) subquery_1 WHERE item_id = 6; -DEBUG: generating subplan 31_1 for subquery SELECT id FROM generate_series((random())::integer, 10) users_ref_test_table(id) -DEBUG: Plan 31 query after replacing subqueries and CTEs: SELECT count(*) AS count FROM (SELECT user_buy_test_table.item_id FROM (public.user_buy_test_table JOIN (SELECT intermediate_result.id FROM read_intermediate_result('31_1'::text, 'binary'::citus_copy_format) intermediate_result(id integer)) users_ref_test_table(id) ON ((user_buy_test_table.item_id OPERATOR(pg_catalog.>) users_ref_test_table.id)))) subquery_1 WHERE (item_id OPERATOR(pg_catalog.=) 6) +DEBUG: generating subplan 35_1 for subquery SELECT id FROM generate_series((random())::integer, 10) users_ref_test_table(id) +DEBUG: Plan 35 query after replacing subqueries and CTEs: SELECT count(*) AS count FROM (SELECT user_buy_test_table.item_id FROM (public.user_buy_test_table JOIN (SELECT intermediate_result.id FROM read_intermediate_result('35_1'::text, 'binary'::citus_copy_format) intermediate_result(id integer)) users_ref_test_table(id) ON ((user_buy_test_table.item_id OPERATOR(pg_catalog.>) users_ref_test_table.id)))) subquery_1 WHERE (item_id OPERATOR(pg_catalog.=) 6) count ------- 0 @@ -305,11 +347,11 @@ SELECT count(*) FROM (SELECT user_id FROM user_buy_test_table UNION ALL SELECT id FROM generate_series(1,10) AS users_ref_test_table(id)) subquery_1; -DEBUG: generating subplan 32_1 for subquery SELECT user_id FROM public.user_buy_test_table +DEBUG: generating subplan 36_1 for subquery SELECT user_id FROM public.user_buy_test_table DEBUG: Creating router plan DEBUG: Plan is router executable -DEBUG: generating subplan 32_2 for subquery SELECT intermediate_result.user_id FROM read_intermediate_result('32_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer) UNION ALL SELECT users_ref_test_table.id FROM generate_series(1, 10) users_ref_test_table(id) -DEBUG: Plan 32 query after replacing subqueries and CTEs: SELECT count(*) AS count FROM (SELECT intermediate_result.user_id FROM read_intermediate_result('32_2'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) subquery_1 +DEBUG: generating subplan 36_2 for subquery SELECT intermediate_result.user_id FROM read_intermediate_result('36_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer) UNION ALL SELECT users_ref_test_table.id FROM generate_series(1, 10) users_ref_test_table(id) +DEBUG: Plan 36 query after replacing subqueries and CTEs: SELECT count(*) AS count FROM (SELECT intermediate_result.user_id FROM read_intermediate_result('36_2'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) subquery_1 DEBUG: Creating router plan DEBUG: Plan is router executable count @@ -343,11 +385,19 @@ ON user_buy_test_table.item_id = users_ref_test_table.id; 4 (1 row) --- subquery without FROM cannot be the outer relationship in an outer join +SET client_min_messages TO DEBUG1; +-- subquery without FROM can be the outer relationship in an outer join +-- since the inner part can be recursively planned SELECT count(*) FROM user_buy_test_table RIGHT JOIN (SELECT 5 AS id) users_ref_test_table ON user_buy_test_table.item_id = users_ref_test_table.id; -ERROR: cannot pushdown the subquery -DETAIL: There exist a subquery without FROM in the outer part of the outer join +DEBUG: generating subplan 42_1 for subquery SELECT NULL::integer AS user_id, item_id, NULL::integer AS buy_count FROM public.user_buy_test_table WHERE true +DEBUG: Plan 42 query after replacing subqueries and CTEs: SELECT count(*) AS count FROM ((SELECT intermediate_result.user_id, intermediate_result.item_id, intermediate_result.buy_count FROM read_intermediate_result('42_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer, item_id integer, buy_count integer)) user_buy_test_table(user_id, item_id, buy_count) RIGHT JOIN (SELECT 5 AS id) users_ref_test_table ON ((user_buy_test_table.item_id OPERATOR(pg_catalog.=) users_ref_test_table.id))) + count +------- + 1 +(1 row) + +RESET client_min_messages; -- can perform a union with subquery without FROM -- with pulling data to coordinator SET client_min_messages TO DEBUG; @@ -355,11 +405,11 @@ SELECT count(*) FROM (SELECT user_id FROM user_buy_test_table UNION ALL SELECT id FROM (SELECT 5 AS id) users_ref_test_table) subquery_1; -DEBUG: generating subplan 39_1 for subquery SELECT user_id FROM public.user_buy_test_table +DEBUG: generating subplan 44_1 for subquery SELECT user_id FROM public.user_buy_test_table DEBUG: Creating router plan DEBUG: Plan is router executable -DEBUG: generating subplan 39_2 for subquery SELECT intermediate_result.user_id FROM read_intermediate_result('39_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer) UNION ALL SELECT users_ref_test_table.id FROM (SELECT 5 AS id) users_ref_test_table -DEBUG: Plan 39 query after replacing subqueries and CTEs: SELECT count(*) AS count FROM (SELECT intermediate_result.user_id FROM read_intermediate_result('39_2'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) subquery_1 +DEBUG: generating subplan 44_2 for subquery SELECT intermediate_result.user_id FROM read_intermediate_result('44_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer) UNION ALL SELECT users_ref_test_table.id FROM (SELECT 5 AS id) users_ref_test_table +DEBUG: Plan 44 query after replacing subqueries and CTEs: SELECT count(*) AS count FROM (SELECT intermediate_result.user_id FROM read_intermediate_result('44_2'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) subquery_1 DEBUG: Creating router plan DEBUG: Plan is router executable count @@ -375,11 +425,11 @@ SELECT * FROM UNION SELECT user_id FROM user_buy_test_table) sub ORDER BY 1 DESC; -DEBUG: generating subplan 42_1 for subquery SELECT user_id FROM public.user_buy_test_table +DEBUG: generating subplan 47_1 for subquery SELECT user_id FROM public.user_buy_test_table DEBUG: Creating router plan DEBUG: Plan is router executable -DEBUG: generating subplan 42_2 for subquery SELECT users_ref_test_table.id FROM public.users_ref_test_table UNION SELECT intermediate_result.user_id FROM read_intermediate_result('42_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer) -DEBUG: Plan 42 query after replacing subqueries and CTEs: SELECT id FROM (SELECT intermediate_result.id FROM read_intermediate_result('42_2'::text, 'binary'::citus_copy_format) intermediate_result(id integer)) sub ORDER BY id DESC +DEBUG: generating subplan 47_2 for subquery SELECT users_ref_test_table.id FROM public.users_ref_test_table UNION SELECT intermediate_result.user_id FROM read_intermediate_result('47_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer) +DEBUG: Plan 47 query after replacing subqueries and CTEs: SELECT id FROM (SELECT intermediate_result.id FROM read_intermediate_result('47_2'::text, 'binary'::citus_copy_format) intermediate_result(id integer)) sub ORDER BY id DESC DEBUG: Creating router plan DEBUG: Plan is router executable id @@ -399,11 +449,11 @@ SELECT * FROM UNION SELECT user_id, random() * 0 FROM (SELECT user_id FROM user_buy_test_table) sub2) sub ORDER BY 1 DESC; -DEBUG: generating subplan 45_1 for subquery SELECT user_id, (random() OPERATOR(pg_catalog.*) (0)::double precision) FROM (SELECT user_buy_test_table.user_id FROM public.user_buy_test_table) sub2 +DEBUG: generating subplan 50_1 for subquery SELECT user_id, (random() OPERATOR(pg_catalog.*) (0)::double precision) FROM (SELECT user_buy_test_table.user_id FROM public.user_buy_test_table) sub2 DEBUG: Creating router plan DEBUG: Plan is router executable -DEBUG: generating subplan 45_2 for subquery SELECT sub1.id, (random() OPERATOR(pg_catalog.*) (0)::double precision) FROM (SELECT users_ref_test_table.id FROM public.users_ref_test_table) sub1 UNION SELECT intermediate_result.user_id, intermediate_result."?column?" FROM read_intermediate_result('45_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer, "?column?" double precision) -DEBUG: Plan 45 query after replacing subqueries and CTEs: SELECT id, "?column?" FROM (SELECT intermediate_result.id, intermediate_result."?column?" FROM read_intermediate_result('45_2'::text, 'binary'::citus_copy_format) intermediate_result(id integer, "?column?" double precision)) sub ORDER BY id DESC +DEBUG: generating subplan 50_2 for subquery SELECT sub1.id, (random() OPERATOR(pg_catalog.*) (0)::double precision) FROM (SELECT users_ref_test_table.id FROM public.users_ref_test_table) sub1 UNION SELECT intermediate_result.user_id, intermediate_result."?column?" FROM read_intermediate_result('50_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer, "?column?" double precision) +DEBUG: Plan 50 query after replacing subqueries and CTEs: SELECT id, "?column?" FROM (SELECT intermediate_result.id, intermediate_result."?column?" FROM read_intermediate_result('50_2'::text, 'binary'::citus_copy_format) intermediate_result(id integer, "?column?" double precision)) sub ORDER BY id DESC DEBUG: Creating router plan DEBUG: Plan is router executable id | ?column? @@ -454,8 +504,16 @@ SELECT * FROM UNION SELECT user_id FROM user_buy_test_table) sub ORDER BY 1 DESC; -ERROR: cannot pushdown the subquery -DETAIL: There exist a reference table in the outer part of the outer join +DEBUG: generating subplan 55_1 for subquery SELECT user_id, NULL::integer AS item_id, NULL::integer AS buy_count FROM public.user_buy_test_table WHERE true +DEBUG: Plan 55 query after replacing subqueries and CTEs: SELECT user_id FROM (SELECT dis.user_id FROM (public.users_ref_test_table ref JOIN public.user_buy_test_table dis ON ((ref.id OPERATOR(pg_catalog.=) dis.user_id))) WHERE (ref.id OPERATOR(pg_catalog.=) ANY (SELECT user_buy_test_table.user_id FROM (SELECT intermediate_result.user_id, intermediate_result.item_id, intermediate_result.buy_count FROM read_intermediate_result('55_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer, item_id integer, buy_count integer)) user_buy_test_table(user_id, item_id, buy_count))) UNION SELECT user_buy_test_table.user_id FROM public.user_buy_test_table) sub ORDER BY user_id DESC + user_id +--------- + 7 + 3 + 2 + 1 +(4 rows) + SELECT * FROM (SELECT user_id FROM users_ref_test_table ref JOIN user_buy_test_table dis on (ref.id = dis.user_id) @@ -495,8 +553,23 @@ SELECT * FROM UNION SELECT user_id FROM user_buy_test_table) sub ORDER BY 1 DESC; -ERROR: cannot pushdown the subquery -DETAIL: There exist a reference table in the outer part of the outer join +DEBUG: generating subplan 59_1 for subquery SELECT user_id, NULL::integer AS item_id, NULL::integer AS buy_count FROM public.user_buy_test_table dis WHERE true +DEBUG: generating subplan 59_2 for subquery SELECT user_id FROM public.user_buy_test_table +DEBUG: Creating router plan +DEBUG: Plan is router executable +DEBUG: generating subplan 59_3 for subquery SELECT user_buy_test_table.user_id FROM (public.users_ref_test_table ref LEFT JOIN (SELECT intermediate_result.user_id, intermediate_result.item_id, intermediate_result.buy_count FROM read_intermediate_result('59_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer, item_id integer, buy_count integer)) user_buy_test_table(user_id, item_id, buy_count) ON ((ref.id OPERATOR(pg_catalog.=) user_buy_test_table.user_id))) UNION SELECT intermediate_result.user_id FROM read_intermediate_result('59_2'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer) +DEBUG: Plan 59 query after replacing subqueries and CTEs: SELECT user_id FROM (SELECT intermediate_result.user_id FROM read_intermediate_result('59_3'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) sub ORDER BY user_id DESC +DEBUG: Creating router plan +DEBUG: Plan is router executable + user_id +--------- + + 7 + 3 + 2 + 1 +(5 rows) + RESET client_min_messages; -- should be able to pushdown since reference table is in the -- inner part of the left join @@ -520,8 +593,10 @@ FROM 6 | 210 (6 rows) --- should not be able to pushdown since reference table is in the --- direct outer part of the left join +SET client_min_messages TO DEBUG1; +-- although the inner part of an outer join with reference table is +-- recursively planned, we still hit the agressive outer join checks +-- (recurring tuple Left Join recurring tuple) errors SELECT user_id, sum(value_1) FROM @@ -532,17 +607,34 @@ FROM LEFT JOIN events_table ON (events_table.user_id = users_table.user_id) ) as foo GROUP BY user_id ORDER BY 2 DESC LIMIT 10; +DEBUG: generating subplan 64_1 for subquery SELECT user_id, NULL::timestamp without time zone AS "time", value_1, NULL::integer AS value_2, NULL::double precision AS value_3, NULL::bigint AS value_4 FROM public.users_table WHERE true +DEBUG: Plan 64 query after replacing subqueries and CTEs: SELECT user_id, sum(value_1) AS sum FROM (SELECT users_table.user_id, users_table.value_1, random() AS random FROM ((public.events_reference_table LEFT JOIN (SELECT intermediate_result.user_id, intermediate_result."time", intermediate_result.value_1, intermediate_result.value_2, intermediate_result.value_3, intermediate_result.value_4 FROM read_intermediate_result('64_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer, "time" timestamp without time zone, value_1 integer, value_2 integer, value_3 double precision, value_4 bigint)) users_table(user_id, "time", value_1, value_2, value_3, value_4) ON ((users_table.user_id OPERATOR(pg_catalog.=) events_reference_table.value_2))) LEFT JOIN public.events_table ON ((events_table.user_id OPERATOR(pg_catalog.=) users_table.user_id)))) foo GROUP BY user_id ORDER BY (sum(value_1)) DESC LIMIT 10 +DEBUG: generating subplan 64_2 for subquery SELECT user_id, NULL::timestamp without time zone AS "time", NULL::integer AS event_type, NULL::integer AS value_2, NULL::double precision AS value_3, NULL::bigint AS value_4 FROM public.events_table WHERE true +DEBUG: Plan 64 query after replacing subqueries and CTEs: SELECT user_id, sum(value_1) AS sum FROM (SELECT users_table.user_id, users_table.value_1, random() AS random FROM ((public.events_reference_table LEFT JOIN (SELECT intermediate_result.user_id, intermediate_result."time", intermediate_result.value_1, intermediate_result.value_2, intermediate_result.value_3, intermediate_result.value_4 FROM read_intermediate_result('64_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer, "time" timestamp without time zone, value_1 integer, value_2 integer, value_3 double precision, value_4 bigint)) users_table(user_id, "time", value_1, value_2, value_3, value_4) ON ((users_table.user_id OPERATOR(pg_catalog.=) events_reference_table.value_2))) LEFT JOIN (SELECT intermediate_result.user_id, intermediate_result."time", intermediate_result.event_type, intermediate_result.value_2, intermediate_result.value_3, intermediate_result.value_4 FROM read_intermediate_result('64_2'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer, "time" timestamp without time zone, event_type integer, value_2 integer, value_3 double precision, value_4 bigint)) events_table(user_id, "time", event_type, value_2, value_3, value_4) ON ((events_table.user_id OPERATOR(pg_catalog.=) users_table.user_id)))) foo GROUP BY user_id ORDER BY (sum(value_1)) DESC LIMIT 10 ERROR: cannot pushdown the subquery -DETAIL: There exist a reference table in the outer part of the outer join --- should not be able to pushdown since reference table is in the --- direct outer part of the left join wrapped into a subquery +DETAIL: Complex subqueries and CTEs cannot be in the outer part of the outer join +-- should be able to pushdown since reference table is in the +-- direct outer part of the left join is recursively planned +-- and the final query becomes a router query SELECT - * + users_table.time, users_table.value_2 FROM (SELECT *, random() FROM events_reference_table) as ref_all LEFT JOIN users_table - ON (users_table.user_id = ref_all.value_2); -ERROR: cannot pushdown the subquery -DETAIL: There exist a reference table in the outer part of the outer join + ON (users_table.user_id = ref_all.value_2) +ORDER BY 1, 2 DESC LIMIT 6; +DEBUG: generating subplan 67_1 for subquery SELECT user_id, "time", NULL::integer AS value_1, value_2, NULL::double precision AS value_3, NULL::bigint AS value_4 FROM public.users_table WHERE true +DEBUG: Plan 67 query after replacing subqueries and CTEs: SELECT users_table."time", users_table.value_2 FROM ((SELECT events_reference_table.user_id, events_reference_table."time", events_reference_table.event_type, events_reference_table.value_2, events_reference_table.value_3, events_reference_table.value_4, random() AS random FROM public.events_reference_table) ref_all LEFT JOIN (SELECT intermediate_result.user_id, intermediate_result."time", intermediate_result.value_1, intermediate_result.value_2, intermediate_result.value_3, intermediate_result.value_4 FROM read_intermediate_result('67_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer, "time" timestamp without time zone, value_1 integer, value_2 integer, value_3 double precision, value_4 bigint)) users_table(user_id, "time", value_1, value_2, value_3, value_4) ON ((users_table.user_id OPERATOR(pg_catalog.=) ref_all.value_2))) ORDER BY users_table."time", users_table.value_2 DESC LIMIT 6 + time | value_2 +---------------------------------+--------- + Wed Nov 22 18:19:49.944985 2017 | 5 + Wed Nov 22 18:19:49.944985 2017 | 5 + Wed Nov 22 18:19:49.944985 2017 | 5 + Wed Nov 22 18:19:49.944985 2017 | 5 + Wed Nov 22 18:19:49.944985 2017 | 5 + Wed Nov 22 18:19:49.944985 2017 | 5 +(6 rows) + +RESET client_min_messages; -- should not be able to pushdown since reference table is in the -- outer part of the left join SELECT @@ -556,7 +648,7 @@ FROM ) as foo GROUP BY user_id ORDER BY 2 DESC LIMIT 10; ERROR: cannot pushdown the subquery -DETAIL: There exist a reference table in the outer part of the outer join +DETAIL: Complex subqueries and CTEs cannot be in the outer part of the outer join -- should be able to pushdown since reference table is in the -- inner part of the left join SELECT * FROM @@ -603,8 +695,14 @@ SELECT * FROM WHERE user_id > 2 and value_2 = 1) as foo_in ON (event_val_2 = user_id)) as foo LEFT JOIN (SELECT user_id as user_user_id FROM users_table) as fooo ON (user_id = user_user_id)) as bar; -ERROR: cannot pushdown the subquery -DETAIL: There exist a reference table in the outer part of the outer join + user_id +--------- + + 3 + 5 + 4 +(4 rows) + -- we could even support the following where the subquery -- on the outer part of the left join contains a reference table SELECT max(events_all.cnt), events_all.usr_id @@ -637,8 +735,15 @@ GROUP BY 2 ORDER BY 1 DESC, 2 DESC LIMIT 5; -ERROR: cannot pushdown the subquery -DETAIL: There exist a reference table in the outer part of the outer join + max | usr_id +-----+-------- + 432 | 2 + 391 | 4 + 364 | 5 + 357 | 3 + 105 | 1 +(5 rows) + -- LATERAL JOINs used with INNER JOINs with reference tables SET citus.subquery_pushdown to ON; SELECT user_id, lastseen @@ -913,8 +1018,9 @@ count(*) AS cnt, "generated_group_field" 84 | 0 (6 rows) - -- RIGHT JOINs used with INNER JOINs should error out since reference table exist in the --- right side of the RIGHT JOIN. + -- RIGHT JOINs used with INNER JOINs should work out since reference table exist in the +-- right side of the RIGHT JOIN and the inner subquery is recursively planned +SET client_min_messages TO DEBUG1; SELECT count(*) AS cnt, "generated_group_field" FROM @@ -951,8 +1057,19 @@ count(*) AS cnt, "generated_group_field" ORDER BY cnt DESC, generated_group_field ASC LIMIT 10; -ERROR: cannot pushdown the subquery -DETAIL: There exist a reference table in the outer part of the outer join +DEBUG: generating subplan 85_1 for subquery SELECT temp_data_queries."time", temp_data_queries.event_user_id, user_filters_1.user_id FROM ((SELECT events."time", events.user_id AS event_user_id FROM public.events_table events WHERE (events.user_id OPERATOR(pg_catalog.>) 2)) temp_data_queries JOIN (SELECT users.user_id FROM public.users_table users WHERE ((users.user_id OPERATOR(pg_catalog.>) 2) AND (users.value_2 OPERATOR(pg_catalog.=) 5))) user_filters_1 ON ((temp_data_queries.event_user_id OPERATOR(pg_catalog.=) user_filters_1.user_id))) +DEBUG: Plan 85 query after replacing subqueries and CTEs: SELECT count(*) AS cnt, generated_group_field FROM (SELECT "eventQuery".user_id, random() AS random, "eventQuery".generated_group_field FROM (SELECT multi_group_wrapper_1."time", multi_group_wrapper_1.event_user_id, multi_group_wrapper_1.user_id, right_group_by_1.generated_group_field, random() AS random FROM ((SELECT intermediate_result."time", intermediate_result.event_user_id, intermediate_result.user_id FROM read_intermediate_result('85_1'::text, 'binary'::citus_copy_format) intermediate_result("time" timestamp without time zone, event_user_id integer, user_id integer)) multi_group_wrapper_1 RIGHT JOIN (SELECT users.user_id, users.value_2 AS generated_group_field FROM public.users_reference_table users) right_group_by_1 ON ((right_group_by_1.user_id OPERATOR(pg_catalog.=) multi_group_wrapper_1.event_user_id)))) "eventQuery") "pushedDownQuery" GROUP BY generated_group_field ORDER BY (count(*)) DESC, generated_group_field LIMIT 10 + cnt | generated_group_field +------+----------------------- + 1007 | 2 + 952 | 5 + 773 | 1 + 696 | 3 + 433 | 4 + 190 | 0 +(6 rows) + +RESET client_min_messages; -- right join where the inner part of the join includes a reference table -- joined with hash partitioned table using non-equi join SELECT user_id, sum(array_length(events_table, 1)), length(hasdone_event), hasdone_event @@ -1315,23 +1432,28 @@ ORDER BY types; 3 | 120 (4 rows) +SET client_min_messages TO DEBUG1; -- just a sanity check that we don't allow this if the reference table is on the --- left part of the left join +-- left part of the left join, we can still recursively plan the inner side SELECT count(*) FROM (SELECT random() FROM users_ref_test_table LEFT JOIN user_buy_test_table ON user_buy_test_table.item_id > users_ref_test_table.id) subquery_1; -ERROR: cannot pushdown the subquery -DETAIL: There exist a reference table in the outer part of the outer join +DEBUG: generating subplan 102_1 for subquery SELECT NULL::integer AS user_id, item_id, NULL::integer AS buy_count FROM public.user_buy_test_table WHERE true +DEBUG: Plan 102 query after replacing subqueries and CTEs: SELECT count(*) AS count FROM (SELECT random() AS random FROM (public.users_ref_test_table LEFT JOIN (SELECT intermediate_result.user_id, intermediate_result.item_id, intermediate_result.buy_count FROM read_intermediate_result('102_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer, item_id integer, buy_count integer)) user_buy_test_table(user_id, item_id, buy_count) ON ((user_buy_test_table.item_id OPERATOR(pg_catalog.>) users_ref_test_table.id)))) subquery_1 + count +------- + 12 +(1 row) + -- we do allow non equi join among subqueries via recursive planning -SET client_min_messages TO DEBUG1; SELECT count(*) FROM (SELECT user_buy_test_table.user_id, random() FROM user_buy_test_table LEFT JOIN users_ref_test_table ON user_buy_test_table.item_id > users_ref_test_table.id) subquery_1, (SELECT user_buy_test_table.user_id, random() FROM user_buy_test_table LEFT JOIN users_ref_test_table ON user_buy_test_table.user_id > users_ref_test_table.id) subquery_2 WHERE subquery_1.user_id != subquery_2.user_id ; -DEBUG: generating subplan 84_1 for subquery SELECT user_buy_test_table.user_id, random() AS random FROM (public.user_buy_test_table LEFT JOIN public.users_ref_test_table ON ((user_buy_test_table.user_id OPERATOR(pg_catalog.>) users_ref_test_table.id))) -DEBUG: Plan 84 query after replacing subqueries and CTEs: SELECT count(*) AS count FROM (SELECT user_buy_test_table.user_id, random() AS random FROM (public.user_buy_test_table LEFT JOIN public.users_ref_test_table ON ((user_buy_test_table.item_id OPERATOR(pg_catalog.>) users_ref_test_table.id)))) subquery_1, (SELECT intermediate_result.user_id, intermediate_result.random FROM read_intermediate_result('84_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer, random double precision)) subquery_2 WHERE (subquery_1.user_id OPERATOR(pg_catalog.<>) subquery_2.user_id) +DEBUG: generating subplan 104_1 for subquery SELECT user_buy_test_table.user_id, random() AS random FROM (public.user_buy_test_table LEFT JOIN public.users_ref_test_table ON ((user_buy_test_table.user_id OPERATOR(pg_catalog.>) users_ref_test_table.id))) +DEBUG: Plan 104 query after replacing subqueries and CTEs: SELECT count(*) AS count FROM (SELECT user_buy_test_table.user_id, random() AS random FROM (public.user_buy_test_table LEFT JOIN public.users_ref_test_table ON ((user_buy_test_table.item_id OPERATOR(pg_catalog.>) users_ref_test_table.id)))) subquery_1, (SELECT intermediate_result.user_id, intermediate_result.random FROM read_intermediate_result('104_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer, random double precision)) subquery_2 WHERE (subquery_1.user_id OPERATOR(pg_catalog.<>) subquery_2.user_id) count ------- 67 @@ -1376,8 +1498,10 @@ count(*) AS cnt, "generated_group_field" ORDER BY cnt DESC, generated_group_field ASC LIMIT 10; -DEBUG: generating subplan 86_1 for subquery SELECT user_id, value_2 AS generated_group_field FROM public.users_table users -DEBUG: Plan 86 query after replacing subqueries and CTEs: SELECT count(*) AS cnt, generated_group_field FROM (SELECT "eventQuery".user_id, random() AS random, "eventQuery".generated_group_field FROM (SELECT multi_group_wrapper_1."time", multi_group_wrapper_1.event_user_id, multi_group_wrapper_1.user_id, left_group_by_1.generated_group_field, random() AS random FROM ((SELECT temp_data_queries."time", temp_data_queries.event_user_id, user_filters_1.user_id FROM ((SELECT events."time", events.user_id AS event_user_id FROM public.events_table events WHERE (events.user_id OPERATOR(pg_catalog.>) 2)) temp_data_queries JOIN (SELECT users.user_id FROM public.users_reference_table users WHERE ((users.user_id OPERATOR(pg_catalog.>) 2) AND (users.value_2 OPERATOR(pg_catalog.=) 5))) user_filters_1 ON ((temp_data_queries.event_user_id OPERATOR(pg_catalog.<) user_filters_1.user_id)))) multi_group_wrapper_1 RIGHT JOIN (SELECT intermediate_result.user_id, intermediate_result.generated_group_field FROM read_intermediate_result('86_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer, generated_group_field integer)) left_group_by_1 ON ((left_group_by_1.user_id OPERATOR(pg_catalog.>) multi_group_wrapper_1.event_user_id)))) "eventQuery") "pushedDownQuery" GROUP BY generated_group_field ORDER BY (count(*)) DESC, generated_group_field LIMIT 10 +DEBUG: generating subplan 106_1 for subquery SELECT user_id, value_2 AS generated_group_field FROM public.users_table users +DEBUG: Plan 106 query after replacing subqueries and CTEs: SELECT count(*) AS cnt, generated_group_field FROM (SELECT "eventQuery".user_id, random() AS random, "eventQuery".generated_group_field FROM (SELECT multi_group_wrapper_1."time", multi_group_wrapper_1.event_user_id, multi_group_wrapper_1.user_id, left_group_by_1.generated_group_field, random() AS random FROM ((SELECT temp_data_queries."time", temp_data_queries.event_user_id, user_filters_1.user_id FROM ((SELECT events."time", events.user_id AS event_user_id FROM public.events_table events WHERE (events.user_id OPERATOR(pg_catalog.>) 2)) temp_data_queries JOIN (SELECT users.user_id FROM public.users_reference_table users WHERE ((users.user_id OPERATOR(pg_catalog.>) 2) AND (users.value_2 OPERATOR(pg_catalog.=) 5))) user_filters_1 ON ((temp_data_queries.event_user_id OPERATOR(pg_catalog.<) user_filters_1.user_id)))) multi_group_wrapper_1 RIGHT JOIN (SELECT intermediate_result.user_id, intermediate_result.generated_group_field FROM read_intermediate_result('106_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer, generated_group_field integer)) left_group_by_1 ON ((left_group_by_1.user_id OPERATOR(pg_catalog.>) multi_group_wrapper_1.event_user_id)))) "eventQuery") "pushedDownQuery" GROUP BY generated_group_field ORDER BY (count(*)) DESC, generated_group_field LIMIT 10 +DEBUG: generating subplan 106_2 for subquery SELECT temp_data_queries."time", temp_data_queries.event_user_id, user_filters_1.user_id FROM ((SELECT events."time", events.user_id AS event_user_id FROM public.events_table events WHERE (events.user_id OPERATOR(pg_catalog.>) 2)) temp_data_queries JOIN (SELECT users.user_id FROM public.users_reference_table users WHERE ((users.user_id OPERATOR(pg_catalog.>) 2) AND (users.value_2 OPERATOR(pg_catalog.=) 5))) user_filters_1 ON ((temp_data_queries.event_user_id OPERATOR(pg_catalog.<) user_filters_1.user_id))) +DEBUG: Plan 106 query after replacing subqueries and CTEs: SELECT count(*) AS cnt, generated_group_field FROM (SELECT "eventQuery".user_id, random() AS random, "eventQuery".generated_group_field FROM (SELECT multi_group_wrapper_1."time", multi_group_wrapper_1.event_user_id, multi_group_wrapper_1.user_id, left_group_by_1.generated_group_field, random() AS random FROM ((SELECT intermediate_result."time", intermediate_result.event_user_id, intermediate_result.user_id FROM read_intermediate_result('106_2'::text, 'binary'::citus_copy_format) intermediate_result("time" timestamp without time zone, event_user_id integer, user_id integer)) multi_group_wrapper_1 RIGHT JOIN (SELECT intermediate_result.user_id, intermediate_result.generated_group_field FROM read_intermediate_result('106_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer, generated_group_field integer)) left_group_by_1 ON ((left_group_by_1.user_id OPERATOR(pg_catalog.>) multi_group_wrapper_1.event_user_id)))) "eventQuery") "pushedDownQuery" GROUP BY generated_group_field ORDER BY (count(*)) DESC, generated_group_field LIMIT 10 ERROR: cannot pushdown the subquery DETAIL: Complex subqueries and CTEs cannot be in the outer part of the outer join RESET client_min_messages; diff --git a/src/test/regress/expected/multi_subquery_in_where_reference_clause.out b/src/test/regress/expected/multi_subquery_in_where_reference_clause.out index 0531e0dd3..c8030fccb 100644 --- a/src/test/regress/expected/multi_subquery_in_where_reference_clause.out +++ b/src/test/regress/expected/multi_subquery_in_where_reference_clause.out @@ -46,8 +46,10 @@ LIMIT 3; --------- (0 rows) --- subqueries in WHERE with NOT EXISTS operator, should not work since --- there is a correlated subquery in WHERE clause +SET client_min_messages TO DEBUG1; +-- although the subquery in WHERE with NOT EXISTS operator (e.g., semi-join) +-- is correlated with the reference table, since events_table can be +-- recursively planned the whole query becomes a router query SELECT user_id FROM @@ -62,10 +64,16 @@ WHERE users_reference_table.user_id = events_table.user_id ) LIMIT 3; -ERROR: cannot pushdown the subquery -DETAIL: Reference tables are not allowed in FROM clause when the query has subqueries in WHERE clause and it references a column from another query --- immutable functions are also treated as reference tables, query should not --- work since there is a correlated subquery in the WHERE clause +DEBUG: generating subplan 3_1 for subquery SELECT user_id, NULL::timestamp without time zone AS "time", NULL::integer AS event_type, NULL::integer AS value_2, NULL::double precision AS value_3, NULL::bigint AS value_4 FROM public.events_table WHERE true +DEBUG: Plan 3 query after replacing subqueries and CTEs: SELECT user_id FROM public.users_reference_table WHERE (NOT (EXISTS (SELECT events_table.value_2 FROM (SELECT intermediate_result.user_id, intermediate_result."time", intermediate_result.event_type, intermediate_result.value_2, intermediate_result.value_3, intermediate_result.value_4 FROM read_intermediate_result('3_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer, "time" timestamp without time zone, event_type integer, value_2 integer, value_3 double precision, value_4 bigint)) events_table(user_id, "time", event_type, value_2, value_3, value_4) WHERE (users_reference_table.user_id OPERATOR(pg_catalog.=) events_table.user_id)))) LIMIT 3 + user_id +--------- +(0 rows) + +-- immutable functions are also treated as reference tables thus +-- although the subquery in WHERE with NOT EXISTS operator (e.g., semi-join) +-- is correlated with the immutable function, since events_table can be +-- recursively planned the whole query becomes a router query SELECT user_id FROM @@ -79,11 +87,21 @@ WHERE WHERE users_reference_table.user_id = events_table.user_id ) +ORDER BY 1 LIMIT 3; -ERROR: cannot pushdown the subquery -DETAIL: Functions are not allowed in FROM clause when the query has subqueries in WHERE clause and it references a column from another query --- subqueries without FROM are also treated as reference tables, query should not --- work since there is a correlated subquery in the WHERE clause +DEBUG: generating subplan 5_1 for subquery SELECT user_id, NULL::timestamp without time zone AS "time", NULL::integer AS event_type, NULL::integer AS value_2, NULL::double precision AS value_3, NULL::bigint AS value_4 FROM public.events_table WHERE true +DEBUG: Plan 5 query after replacing subqueries and CTEs: SELECT user_id FROM (SELECT series.user_id FROM generate_series(1, 10) series(user_id)) users_reference_table WHERE (NOT (EXISTS (SELECT events_table.value_2 FROM (SELECT intermediate_result.user_id, intermediate_result."time", intermediate_result.event_type, intermediate_result.value_2, intermediate_result.value_3, intermediate_result.value_4 FROM read_intermediate_result('5_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer, "time" timestamp without time zone, event_type integer, value_2 integer, value_3 double precision, value_4 bigint)) events_table(user_id, "time", event_type, value_2, value_3, value_4) WHERE (users_reference_table.user_id OPERATOR(pg_catalog.=) events_table.user_id)))) ORDER BY user_id LIMIT 3 + user_id +--------- + 7 + 8 + 9 +(3 rows) + +-- subqueries without FROM are also treated as reference tables thus +-- although the subquery in WHERE with NOT EXISTS operator (e.g., semi-join) +-- is correlated with the subquery, since events_table can be +-- recursively planned the whole query becomes a router query SELECT user_id FROM @@ -98,8 +116,13 @@ WHERE users_reference_table.user_id = events_table.user_id ) LIMIT 3; -ERROR: cannot pushdown the subquery -DETAIL: Subqueries without FROM are not allowed in FROM clause when the outer query has subqueries in WHERE clause and it references a column from another query +DEBUG: generating subplan 7_1 for subquery SELECT user_id, NULL::timestamp without time zone AS "time", NULL::integer AS event_type, NULL::integer AS value_2, NULL::double precision AS value_3, NULL::bigint AS value_4 FROM public.events_table WHERE true +DEBUG: Plan 7 query after replacing subqueries and CTEs: SELECT user_id FROM (SELECT 5 AS user_id) users_reference_table WHERE (NOT (EXISTS (SELECT events_table.value_2 FROM (SELECT intermediate_result.user_id, intermediate_result."time", intermediate_result.event_type, intermediate_result.value_2, intermediate_result.value_3, intermediate_result.value_4 FROM read_intermediate_result('7_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer, "time" timestamp without time zone, event_type integer, value_2 integer, value_3 double precision, value_4 bigint)) events_table(user_id, "time", event_type, value_2, value_3, value_4) WHERE (users_reference_table.user_id OPERATOR(pg_catalog.=) events_table.user_id)))) LIMIT 3 + user_id +--------- +(0 rows) + +RESET client_min_messages; -- join with distributed table prevents FROM from recurring SELECT DISTINCT user_id @@ -166,7 +189,7 @@ WHERE ORDER BY user_id LIMIT 3; ERROR: cannot pushdown the subquery -DETAIL: There exist a reference table in the outer part of the outer join +DETAIL: Complex subqueries and CTEs are not allowed in the FROM clause when the query has subqueries in the WHERE clause and it references a column from another query -- subqueries in WHERE with IN operator without equality SELECT users_table.user_id, count(*) @@ -491,8 +514,8 @@ FROM WHERE user_id NOT IN (SELECT users_table.value_2 FROM users_table JOIN users_reference_table as u2 ON users_table.value_2 = u2.value_2); -DEBUG: generating subplan 18_1 for subquery SELECT users_table.value_2 FROM (public.users_table JOIN public.users_reference_table u2 ON ((users_table.value_2 OPERATOR(pg_catalog.=) u2.value_2))) -DEBUG: Plan 18 query after replacing subqueries and CTEs: SELECT count(*) AS count FROM public.users_reference_table WHERE (NOT (user_id OPERATOR(pg_catalog.=) ANY (SELECT intermediate_result.value_2 FROM read_intermediate_result('18_1'::text, 'binary'::citus_copy_format) intermediate_result(value_2 integer)))) +DEBUG: generating subplan 22_1 for subquery SELECT users_table.value_2 FROM (public.users_table JOIN public.users_reference_table u2 ON ((users_table.value_2 OPERATOR(pg_catalog.=) u2.value_2))) +DEBUG: Plan 22 query after replacing subqueries and CTEs: SELECT count(*) AS count FROM public.users_reference_table WHERE (NOT (user_id OPERATOR(pg_catalog.=) ANY (SELECT intermediate_result.value_2 FROM read_intermediate_result('22_1'::text, 'binary'::citus_copy_format) intermediate_result(value_2 integer)))) count ------- 10 @@ -507,8 +530,8 @@ FROM (SELECT users_table.value_2 FROM users_table JOIN users_reference_table AS u2 ON users_table.value_2 = u2.value_2); -DEBUG: generating subplan 20_1 for subquery SELECT users_table.value_2 FROM (public.users_table JOIN public.users_reference_table u2 ON ((users_table.value_2 OPERATOR(pg_catalog.=) u2.value_2))) -DEBUG: Plan 20 query after replacing subqueries and CTEs: SELECT count(*) AS count FROM (SELECT users_reference_table.user_id, random() AS random FROM public.users_reference_table) vals WHERE (NOT (user_id OPERATOR(pg_catalog.=) ANY (SELECT intermediate_result.value_2 FROM read_intermediate_result('20_1'::text, 'binary'::citus_copy_format) intermediate_result(value_2 integer)))) +DEBUG: generating subplan 24_1 for subquery SELECT users_table.value_2 FROM (public.users_table JOIN public.users_reference_table u2 ON ((users_table.value_2 OPERATOR(pg_catalog.=) u2.value_2))) +DEBUG: Plan 24 query after replacing subqueries and CTEs: SELECT count(*) AS count FROM (SELECT users_reference_table.user_id, random() AS random FROM public.users_reference_table) vals WHERE (NOT (user_id OPERATOR(pg_catalog.=) ANY (SELECT intermediate_result.value_2 FROM read_intermediate_result('24_1'::text, 'binary'::citus_copy_format) intermediate_result(value_2 integer)))) count ------- 10 diff --git a/src/test/regress/expected/multi_view.out b/src/test/regress/expected/multi_view.out index f06afa368..36cd2cc01 100644 --- a/src/test/regress/expected/multi_view.out +++ b/src/test/regress/expected/multi_view.out @@ -875,7 +875,7 @@ EXPLAIN (COSTS FALSE) SELECT et.* FROM recent_10_users JOIN events_table et USIN -> Sort Sort Key: remote_scan."time" DESC -> Custom Scan (Citus Real-Time) - -> Distributed Subplan 96_1 + -> Distributed Subplan 97_1 -> Limit -> Sort Sort Key: max((max(remote_scan.lastseen))) DESC diff --git a/src/test/regress/expected/set_operation_and_local_tables.out b/src/test/regress/expected/set_operation_and_local_tables.out index daf3e7a4a..7aa916b96 100644 --- a/src/test/regress/expected/set_operation_and_local_tables.out +++ b/src/test/regress/expected/set_operation_and_local_tables.out @@ -231,17 +231,19 @@ DEBUG: Creating router plan DEBUG: Plan is router executable DEBUG: generating subplan 39_3 for subquery SELECT intermediate_result.x, intermediate_result.y FROM read_intermediate_result('39_1'::text, 'binary'::citus_copy_format) intermediate_result(x integer, y integer) INTERSECT SELECT intermediate_result.x, intermediate_result.y FROM read_intermediate_result('39_2'::text, 'binary'::citus_copy_format) intermediate_result(x integer, y integer) DEBUG: Plan 39 query after replacing subqueries and CTEs: SELECT u.x, u.y, test.y FROM ((SELECT intermediate_result.x, intermediate_result.y FROM read_intermediate_result('39_3'::text, 'binary'::citus_copy_format) intermediate_result(x integer, y integer)) u LEFT JOIN recursive_set_local.test USING (x)) ORDER BY u.x, u.y +DEBUG: generating subplan 39_4 for subquery SELECT x, y FROM recursive_set_local.test WHERE true +DEBUG: Plan 39 query after replacing subqueries and CTEs: SELECT u.x, u.y, test.y FROM ((SELECT intermediate_result.x, intermediate_result.y FROM read_intermediate_result('39_3'::text, 'binary'::citus_copy_format) intermediate_result(x integer, y integer)) u LEFT JOIN (SELECT intermediate_result.x, intermediate_result.y FROM read_intermediate_result('39_4'::text, 'binary'::citus_copy_format) intermediate_result(x integer, y integer)) test(x, y) USING (x)) ORDER BY u.x, u.y ERROR: cannot pushdown the subquery DETAIL: Complex subqueries and CTEs cannot be in the outer part of the outer join -- we replace some queries including the local query, the intermediate result is on the inner part of an outer join SELECT * FROM ((SELECT * FROM local_test) INTERSECT (SELECT * FROM test ORDER BY x LIMIT 1)) u RIGHT JOIN test USING (x) ORDER BY 1,2; -DEBUG: generating subplan 42_1 for subquery SELECT x, y FROM recursive_set_local.local_test +DEBUG: generating subplan 43_1 for subquery SELECT x, y FROM recursive_set_local.local_test DEBUG: push down of limit count: 1 -DEBUG: generating subplan 42_2 for subquery SELECT x, y FROM recursive_set_local.test ORDER BY x LIMIT 1 +DEBUG: generating subplan 43_2 for subquery SELECT x, y FROM recursive_set_local.test ORDER BY x LIMIT 1 DEBUG: Creating router plan DEBUG: Plan is router executable -DEBUG: generating subplan 42_3 for subquery SELECT intermediate_result.x, intermediate_result.y FROM read_intermediate_result('42_1'::text, 'binary'::citus_copy_format) intermediate_result(x integer, y integer) INTERSECT SELECT intermediate_result.x, intermediate_result.y FROM read_intermediate_result('42_2'::text, 'binary'::citus_copy_format) intermediate_result(x integer, y integer) -DEBUG: Plan 42 query after replacing subqueries and CTEs: SELECT test.x, u.y, test.y FROM ((SELECT intermediate_result.x, intermediate_result.y FROM read_intermediate_result('42_3'::text, 'binary'::citus_copy_format) intermediate_result(x integer, y integer)) u RIGHT JOIN recursive_set_local.test USING (x)) ORDER BY test.x, u.y +DEBUG: generating subplan 43_3 for subquery SELECT intermediate_result.x, intermediate_result.y FROM read_intermediate_result('43_1'::text, 'binary'::citus_copy_format) intermediate_result(x integer, y integer) INTERSECT SELECT intermediate_result.x, intermediate_result.y FROM read_intermediate_result('43_2'::text, 'binary'::citus_copy_format) intermediate_result(x integer, y integer) +DEBUG: Plan 43 query after replacing subqueries and CTEs: SELECT test.x, u.y, test.y FROM ((SELECT intermediate_result.x, intermediate_result.y FROM read_intermediate_result('43_3'::text, 'binary'::citus_copy_format) intermediate_result(x integer, y integer)) u RIGHT JOIN recursive_set_local.test USING (x)) ORDER BY test.x, u.y x | y | y ---+---+--- 1 | | 1 @@ -250,29 +252,29 @@ DEBUG: Plan 42 query after replacing subqueries and CTEs: SELECT test.x, u.y, t -- recurively plan left part of the join, and run a final real-time query SELECT * FROM ((SELECT * FROM local_test) INTERSECT (SELECT * FROM test ORDER BY x LIMIT 1)) u INNER JOIN test USING (x) ORDER BY 1,2; -DEBUG: generating subplan 45_1 for subquery SELECT x, y FROM recursive_set_local.local_test +DEBUG: generating subplan 46_1 for subquery SELECT x, y FROM recursive_set_local.local_test DEBUG: push down of limit count: 1 -DEBUG: generating subplan 45_2 for subquery SELECT x, y FROM recursive_set_local.test ORDER BY x LIMIT 1 +DEBUG: generating subplan 46_2 for subquery SELECT x, y FROM recursive_set_local.test ORDER BY x LIMIT 1 DEBUG: Creating router plan DEBUG: Plan is router executable -DEBUG: generating subplan 45_3 for subquery SELECT intermediate_result.x, intermediate_result.y FROM read_intermediate_result('45_1'::text, 'binary'::citus_copy_format) intermediate_result(x integer, y integer) INTERSECT SELECT intermediate_result.x, intermediate_result.y FROM read_intermediate_result('45_2'::text, 'binary'::citus_copy_format) intermediate_result(x integer, y integer) -DEBUG: Plan 45 query after replacing subqueries and CTEs: SELECT u.x, u.y, test.y FROM ((SELECT intermediate_result.x, intermediate_result.y FROM read_intermediate_result('45_3'::text, 'binary'::citus_copy_format) intermediate_result(x integer, y integer)) u JOIN recursive_set_local.test USING (x)) ORDER BY u.x, u.y +DEBUG: generating subplan 46_3 for subquery SELECT intermediate_result.x, intermediate_result.y FROM read_intermediate_result('46_1'::text, 'binary'::citus_copy_format) intermediate_result(x integer, y integer) INTERSECT SELECT intermediate_result.x, intermediate_result.y FROM read_intermediate_result('46_2'::text, 'binary'::citus_copy_format) intermediate_result(x integer, y integer) +DEBUG: Plan 46 query after replacing subqueries and CTEs: SELECT u.x, u.y, test.y FROM ((SELECT intermediate_result.x, intermediate_result.y FROM read_intermediate_result('46_3'::text, 'binary'::citus_copy_format) intermediate_result(x integer, y integer)) u JOIN recursive_set_local.test USING (x)) ORDER BY u.x, u.y x | y | y ---+---+--- (0 rows) -- set operations and the sublink can be recursively planned SELECT * FROM ((SELECT x FROM test) UNION (SELECT x FROM (SELECT x FROM local_test) as foo WHERE x IN (SELECT x FROM test))) u ORDER BY 1; -DEBUG: generating subplan 48_1 for subquery SELECT x FROM recursive_set_local.local_test -DEBUG: generating subplan 48_2 for subquery SELECT x FROM recursive_set_local.test +DEBUG: generating subplan 49_1 for subquery SELECT x FROM recursive_set_local.local_test +DEBUG: generating subplan 49_2 for subquery SELECT x FROM recursive_set_local.test DEBUG: Creating router plan DEBUG: Plan is router executable -DEBUG: generating subplan 48_3 for subquery SELECT x FROM (SELECT intermediate_result.x FROM read_intermediate_result('48_1'::text, 'binary'::citus_copy_format) intermediate_result(x integer)) foo WHERE (x OPERATOR(pg_catalog.=) ANY (SELECT intermediate_result.x FROM read_intermediate_result('48_2'::text, 'binary'::citus_copy_format) intermediate_result(x integer))) -DEBUG: generating subplan 48_4 for subquery SELECT x FROM recursive_set_local.test +DEBUG: generating subplan 49_3 for subquery SELECT x FROM (SELECT intermediate_result.x FROM read_intermediate_result('49_1'::text, 'binary'::citus_copy_format) intermediate_result(x integer)) foo WHERE (x OPERATOR(pg_catalog.=) ANY (SELECT intermediate_result.x FROM read_intermediate_result('49_2'::text, 'binary'::citus_copy_format) intermediate_result(x integer))) +DEBUG: generating subplan 49_4 for subquery SELECT x FROM recursive_set_local.test DEBUG: Creating router plan DEBUG: Plan is router executable -DEBUG: generating subplan 48_5 for subquery SELECT intermediate_result.x FROM read_intermediate_result('48_4'::text, 'binary'::citus_copy_format) intermediate_result(x integer) UNION SELECT intermediate_result.x FROM read_intermediate_result('48_3'::text, 'binary'::citus_copy_format) intermediate_result(x integer) -DEBUG: Plan 48 query after replacing subqueries and CTEs: SELECT x FROM (SELECT intermediate_result.x FROM read_intermediate_result('48_5'::text, 'binary'::citus_copy_format) intermediate_result(x integer)) u ORDER BY x +DEBUG: generating subplan 49_5 for subquery SELECT intermediate_result.x FROM read_intermediate_result('49_4'::text, 'binary'::citus_copy_format) intermediate_result(x integer) UNION SELECT intermediate_result.x FROM read_intermediate_result('49_3'::text, 'binary'::citus_copy_format) intermediate_result(x integer) +DEBUG: Plan 49 query after replacing subqueries and CTEs: SELECT x FROM (SELECT intermediate_result.x FROM read_intermediate_result('49_5'::text, 'binary'::citus_copy_format) intermediate_result(x integer)) u ORDER BY x DEBUG: Creating router plan DEBUG: Plan is router executable x @@ -315,11 +317,11 @@ DEBUG: pruning merge fetch taskId 11 DETAIL: Creating dependency on merge taskId 20 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 53_1 for subquery SELECT t1.x FROM recursive_set_local.test t1, recursive_set_local.test t2 WHERE (t1.x OPERATOR(pg_catalog.=) t2.y) LIMIT 2 -DEBUG: generating subplan 53_2 for subquery SELECT x FROM recursive_set_local.local_test -DEBUG: generating subplan 53_3 for subquery SELECT x FROM recursive_set_local.test -DEBUG: generating subplan 53_4 for subquery SELECT x FROM recursive_set_local.test -DEBUG: Plan 53 query after replacing subqueries and CTEs: SELECT intermediate_result.x FROM read_intermediate_result('53_3'::text, 'binary'::citus_copy_format) intermediate_result(x integer) INTERSECT SELECT intermediate_result.x FROM read_intermediate_result('53_1'::text, 'binary'::citus_copy_format) intermediate_result(x integer) INTERSECT ((SELECT intermediate_result.x FROM read_intermediate_result('53_2'::text, 'binary'::citus_copy_format) intermediate_result(x integer) UNION ALL SELECT intermediate_result.x FROM read_intermediate_result('53_4'::text, 'binary'::citus_copy_format) intermediate_result(x integer)) INTERSECT SELECT i.i FROM generate_series(0, 100) i(i)) ORDER BY 1 DESC +DEBUG: generating subplan 54_1 for subquery SELECT t1.x FROM recursive_set_local.test t1, recursive_set_local.test t2 WHERE (t1.x OPERATOR(pg_catalog.=) t2.y) LIMIT 2 +DEBUG: generating subplan 54_2 for subquery SELECT x FROM recursive_set_local.local_test +DEBUG: generating subplan 54_3 for subquery SELECT x FROM recursive_set_local.test +DEBUG: generating subplan 54_4 for subquery SELECT x FROM recursive_set_local.test +DEBUG: Plan 54 query after replacing subqueries and CTEs: SELECT intermediate_result.x FROM read_intermediate_result('54_3'::text, 'binary'::citus_copy_format) intermediate_result(x integer) INTERSECT SELECT intermediate_result.x FROM read_intermediate_result('54_1'::text, 'binary'::citus_copy_format) intermediate_result(x integer) INTERSECT ((SELECT intermediate_result.x FROM read_intermediate_result('54_2'::text, 'binary'::citus_copy_format) intermediate_result(x integer) UNION ALL SELECT intermediate_result.x FROM read_intermediate_result('54_4'::text, 'binary'::citus_copy_format) intermediate_result(x integer)) INTERSECT SELECT i.i FROM generate_series(0, 100) i(i)) ORDER BY 1 DESC DEBUG: Creating router plan DEBUG: Plan is router executable x diff --git a/src/test/regress/expected/set_operations.out b/src/test/regress/expected/set_operations.out index cf7761c70..efdcb8741 100644 --- a/src/test/regress/expected/set_operations.out +++ b/src/test/regress/expected/set_operations.out @@ -510,13 +510,8 @@ DEBUG: generating subplan 101_1 for subquery SELECT x, y FROM recursive_union.t DEBUG: generating subplan 101_2 for subquery SELECT x, y FROM recursive_union.test ORDER BY x DEBUG: Creating router plan DEBUG: Plan is router executable -<<<<<<< HEAD -DEBUG: generating subplan 100_3 for subquery SELECT intermediate_result.x, intermediate_result.y FROM read_intermediate_result('100_1'::text, 'binary'::citus_copy_format) intermediate_result(x integer, y integer) EXCEPT SELECT intermediate_result.x, intermediate_result.y FROM read_intermediate_result('100_2'::text, 'binary'::citus_copy_format) intermediate_result(x integer, y integer) -DEBUG: Plan 100 query after replacing subqueries and CTEs: SELECT u.x, u.y FROM ((SELECT intermediate_result.x, intermediate_result.y FROM read_intermediate_result('100_3'::text, 'binary'::citus_copy_format) intermediate_result(x integer, y integer)) u JOIN (SELECT x_1.x FROM generate_series(1, 10) x_1(x)) x USING (x)) ORDER BY u.x, u.y -======= DEBUG: generating subplan 101_3 for subquery SELECT intermediate_result.x, intermediate_result.y FROM read_intermediate_result('101_1'::text, 'binary'::citus_copy_format) intermediate_result(x integer, y integer) EXCEPT SELECT intermediate_result.x, intermediate_result.y FROM read_intermediate_result('101_2'::text, 'binary'::citus_copy_format) intermediate_result(x integer, y integer) -DEBUG: Plan 101 query after replacing subqueries and CTEs: SELECT u.x, u.y FROM ((SELECT intermediate_result.x, intermediate_result.y FROM read_intermediate_result('101_3'::text, 'binary'::citus_copy_format) intermediate_result(x integer, y integer)) u JOIN generate_series(1, 10) x(x) USING (x)) ORDER BY u.x, u.y ->>>>>>> e2f99a04... Recursively plan inner parts of recurring tuple joins +DEBUG: Plan 101 query after replacing subqueries and CTEs: SELECT u.x, u.y FROM ((SELECT intermediate_result.x, intermediate_result.y FROM read_intermediate_result('101_3'::text, 'binary'::citus_copy_format) intermediate_result(x integer, y integer)) u JOIN (SELECT x_1.x FROM generate_series(1, 10) x_1(x)) x USING (x)) ORDER BY u.x, u.y DEBUG: Creating router plan DEBUG: Plan is router executable x | y diff --git a/src/test/regress/expected/subqueries_not_supported.out b/src/test/regress/expected/subqueries_not_supported.out index 2ee0aa9cd..8d2a3f6bf 100644 --- a/src/test/regress/expected/subqueries_not_supported.out +++ b/src/test/regress/expected/subqueries_not_supported.out @@ -115,6 +115,8 @@ FROM DEBUG: push down of limit count: 5 DEBUG: generating subplan 14_1 for subquery SELECT users_table.value_2 FROM public.users_table, public.events_table WHERE ((users_table.user_id OPERATOR(pg_catalog.=) events_table.user_id) AND (events_table.event_type OPERATOR(pg_catalog.=) ANY (ARRAY[1, 2, 3, 4]))) LIMIT 5 DEBUG: Plan 14 query after replacing subqueries and CTEs: SELECT foo.value_2 FROM ((SELECT intermediate_result.value_2 FROM read_intermediate_result('14_1'::text, 'binary'::citus_copy_format) intermediate_result(value_2 integer)) foo LEFT JOIN (SELECT users_table.value_2 FROM public.users_table, public.events_table WHERE ((users_table.user_id OPERATOR(pg_catalog.=) events_table.user_id) AND (events_table.event_type OPERATOR(pg_catalog.=) ANY (ARRAY[5, 6, 7, 8])))) bar ON ((foo.value_2 OPERATOR(pg_catalog.=) bar.value_2))) +DEBUG: generating subplan 14_2 for subquery SELECT users_table.value_2 FROM public.users_table, public.events_table WHERE ((users_table.user_id OPERATOR(pg_catalog.=) events_table.user_id) AND (events_table.event_type OPERATOR(pg_catalog.=) ANY (ARRAY[5, 6, 7, 8]))) +DEBUG: Plan 14 query after replacing subqueries and CTEs: SELECT foo.value_2 FROM ((SELECT intermediate_result.value_2 FROM read_intermediate_result('14_1'::text, 'binary'::citus_copy_format) intermediate_result(value_2 integer)) foo LEFT JOIN (SELECT intermediate_result.value_2 FROM read_intermediate_result('14_2'::text, 'binary'::citus_copy_format) intermediate_result(value_2 integer)) bar ON ((foo.value_2 OPERATOR(pg_catalog.=) bar.value_2))) ERROR: cannot pushdown the subquery DETAIL: Complex subqueries and CTEs cannot be in the outer part of the outer join -- Aggregates in subquery without partition column can be planned recursively diff --git a/src/test/regress/expected/subquery_in_where.out b/src/test/regress/expected/subquery_in_where.out index ad583faa9..35e8776c8 100644 --- a/src/test/regress/expected/subquery_in_where.out +++ b/src/test/regress/expected/subquery_in_where.out @@ -44,8 +44,8 @@ FROM (SELECT 1 AS id, 3 AS value_3) AS tt1 WHERE id IN (SELECT user_id FROM events_table); -DEBUG: generating subplan 6_1 for subquery SELECT user_id FROM public.events_table -DEBUG: Plan 6 query after replacing subqueries and CTEs: SELECT id, value_1, value_3 FROM (SELECT 1 AS id, 2 AS value_1, 3 AS value_3) tt1 WHERE (id OPERATOR(pg_catalog.=) ANY (SELECT intermediate_result.user_id FROM read_intermediate_result('6_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer))) +DEBUG: generating subplan 6_1 for subquery SELECT user_id, NULL::timestamp without time zone AS "time", NULL::integer AS event_type, NULL::integer AS value_2, NULL::double precision AS value_3, NULL::bigint AS value_4 FROM public.events_table WHERE true +DEBUG: Plan 6 query after replacing subqueries and CTEs: SELECT id, value_1, value_3 FROM (SELECT 1 AS id, 2 AS value_1, 3 AS value_3) tt1 WHERE (id OPERATOR(pg_catalog.=) ANY (SELECT events_table.user_id FROM (SELECT intermediate_result.user_id, intermediate_result."time", intermediate_result.event_type, intermediate_result.value_2, intermediate_result.value_3, intermediate_result.value_4 FROM read_intermediate_result('6_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer, "time" timestamp without time zone, event_type integer, value_2 integer, value_3 double precision, value_4 bigint)) events_table(user_id, "time", event_type, value_2, value_3, value_4))) id | value_1 | value_3 ----+---------+--------- 1 | 2 | 3 @@ -580,8 +580,8 @@ IN ) ORDER BY generate_series ASC; -DEBUG: generating subplan 63_1 for subquery SELECT value_2 FROM public.events_table -DEBUG: Plan 63 query after replacing subqueries and CTEs: SELECT generate_series FROM (SELECT generate_series.generate_series FROM generate_series(1, 10) generate_series(generate_series)) gst WHERE (generate_series OPERATOR(pg_catalog.=) ANY (SELECT intermediate_result.value_2 FROM read_intermediate_result('63_1'::text, 'binary'::citus_copy_format) intermediate_result(value_2 integer))) ORDER BY generate_series +DEBUG: generating subplan 63_1 for subquery SELECT NULL::integer AS user_id, NULL::timestamp without time zone AS "time", NULL::integer AS event_type, value_2, NULL::double precision AS value_3, NULL::bigint AS value_4 FROM public.events_table WHERE true +DEBUG: Plan 63 query after replacing subqueries and CTEs: SELECT generate_series FROM (SELECT generate_series.generate_series FROM generate_series(1, 10) generate_series(generate_series)) gst WHERE (generate_series OPERATOR(pg_catalog.=) ANY (SELECT events_table.value_2 FROM (SELECT intermediate_result.user_id, intermediate_result."time", intermediate_result.event_type, intermediate_result.value_2, intermediate_result.value_3, intermediate_result.value_4 FROM read_intermediate_result('63_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer, "time" timestamp without time zone, event_type integer, value_2 integer, value_3 double precision, value_4 bigint)) events_table(user_id, "time", event_type, value_2, value_3, value_4))) ORDER BY generate_series generate_series ----------------- 1 @@ -618,8 +618,9 @@ IN ) ORDER BY generate_series ASC; -DEBUG: generating subplan 65_1 for subquery SELECT user_id FROM public.users_table WHERE (user_id OPERATOR(pg_catalog.=) ANY (SELECT generate_series.generate_series FROM generate_series(1, 3) generate_series(generate_series))) -DEBUG: Plan 65 query after replacing subqueries and CTEs: SELECT generate_series FROM (SELECT generate_series.generate_series FROM generate_series(1, 10) generate_series(generate_series)) gst WHERE (generate_series OPERATOR(pg_catalog.=) ANY (SELECT intermediate_result.user_id FROM read_intermediate_result('65_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer))) ORDER BY generate_series +DEBUG: generating subplan 65_1 for subquery SELECT user_id, NULL::timestamp without time zone AS "time", NULL::integer AS value_1, NULL::integer AS value_2, NULL::double precision AS value_3, NULL::bigint AS value_4 FROM public.users_table WHERE true +DEBUG: generating subplan 65_2 for subquery SELECT user_id FROM (SELECT intermediate_result.user_id, intermediate_result."time", intermediate_result.value_1, intermediate_result.value_2, intermediate_result.value_3, intermediate_result.value_4 FROM read_intermediate_result('65_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer, "time" timestamp without time zone, value_1 integer, value_2 integer, value_3 double precision, value_4 bigint)) users_table(user_id, "time", value_1, value_2, value_3, value_4) WHERE (user_id OPERATOR(pg_catalog.=) ANY (SELECT generate_series.generate_series FROM generate_series(1, 3) generate_series(generate_series))) +DEBUG: Plan 65 query after replacing subqueries and CTEs: SELECT generate_series FROM (SELECT generate_series.generate_series FROM generate_series(1, 10) generate_series(generate_series)) gst WHERE (generate_series OPERATOR(pg_catalog.=) ANY (SELECT intermediate_result.user_id FROM read_intermediate_result('65_2'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer))) ORDER BY generate_series generate_series ----------------- 1 @@ -646,9 +647,9 @@ IN user_id FROM users_table); -DEBUG: generating subplan 67_1 for subquery SELECT id, value_1 FROM subquery_in_where.local_table -DEBUG: generating subplan 67_2 for subquery SELECT user_id FROM public.users_table -DEBUG: Plan 67 query after replacing subqueries and CTEs: SELECT id, value_1 FROM (SELECT intermediate_result.id, intermediate_result.value_1 FROM read_intermediate_result('67_1'::text, 'binary'::citus_copy_format) intermediate_result(id integer, value_1 integer)) sub_table WHERE (id OPERATOR(pg_catalog.=) ANY (SELECT intermediate_result.user_id FROM read_intermediate_result('67_2'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer))) +DEBUG: generating subplan 68_1 for subquery SELECT id, value_1 FROM subquery_in_where.local_table +DEBUG: generating subplan 68_2 for subquery SELECT user_id FROM public.users_table +DEBUG: Plan 68 query after replacing subqueries and CTEs: SELECT id, value_1 FROM (SELECT intermediate_result.id, intermediate_result.value_1 FROM read_intermediate_result('68_1'::text, 'binary'::citus_copy_format) intermediate_result(id integer, value_1 integer)) sub_table WHERE (id OPERATOR(pg_catalog.=) ANY (SELECT intermediate_result.user_id FROM read_intermediate_result('68_2'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer))) id | value_1 ----+--------- 1 | 1 @@ -675,10 +676,10 @@ IN id FROM local_table); -DEBUG: generating subplan 69_1 for subquery SELECT id FROM subquery_in_where.local_table +DEBUG: generating subplan 70_1 for subquery SELECT id FROM subquery_in_where.local_table DEBUG: push down of limit count: 10 -DEBUG: generating subplan 69_2 for subquery SELECT user_id, "time", value_1, value_2, value_3, value_4 FROM public.users_table ORDER BY user_id LIMIT 10 -DEBUG: Plan 69 query after replacing subqueries and CTEs: SELECT count(*) AS count FROM (SELECT intermediate_result.user_id, intermediate_result."time", intermediate_result.value_1, intermediate_result.value_2, intermediate_result.value_3, intermediate_result.value_4 FROM read_intermediate_result('69_2'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer, "time" timestamp without time zone, value_1 integer, value_2 integer, value_3 double precision, value_4 bigint)) sub_table WHERE (user_id OPERATOR(pg_catalog.=) ANY (SELECT intermediate_result.id FROM read_intermediate_result('69_1'::text, 'binary'::citus_copy_format) intermediate_result(id integer))) +DEBUG: generating subplan 70_2 for subquery SELECT user_id, "time", value_1, value_2, value_3, value_4 FROM public.users_table ORDER BY user_id LIMIT 10 +DEBUG: Plan 70 query after replacing subqueries and CTEs: SELECT count(*) AS count FROM (SELECT intermediate_result.user_id, intermediate_result."time", intermediate_result.value_1, intermediate_result.value_2, intermediate_result.value_3, intermediate_result.value_4 FROM read_intermediate_result('70_2'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer, "time" timestamp without time zone, value_1 integer, value_2 integer, value_3 double precision, value_4 bigint)) sub_table WHERE (user_id OPERATOR(pg_catalog.=) ANY (SELECT intermediate_result.id FROM read_intermediate_result('70_1'::text, 'binary'::citus_copy_format) intermediate_result(id integer))) count ------- 10 diff --git a/src/test/regress/input/multi_outer_join_reference.source b/src/test/regress/input/multi_outer_join_reference.source index 32d35cd45..bcb52b483 100644 --- a/src/test/regress/input/multi_outer_join_reference.source +++ b/src/test/regress/input/multi_outer_join_reference.source @@ -149,12 +149,15 @@ FROM multi_outer_join_left_hash a LEFT JOIN multi_outer_join_right_reference b ON (l_custkey = r_custkey AND l_custkey = -1 /* nonexistant */); --- Right join should be disallowed in this case +SET client_min_messages TO DEBUG1; +-- Right join should be allowed in this case +-- since the table in the inner part can be recursively +-- planned SELECT min(r_custkey), max(r_custkey) FROM multi_outer_join_left_hash a RIGHT JOIN multi_outer_join_right_reference b ON (l_custkey = r_custkey); - +SET client_min_messages TO LOG; -- Reverse right join should be same as left join SELECT @@ -243,13 +246,15 @@ FROM multi_outer_join_left_hash a LEFT JOIN multi_outer_join_right_reference b ON (l_custkey = r_custkey AND r_custkey = 21); - --- Right join should not be allowed in this case +SET client_min_messages TO DEBUG; +-- Right join should be allowed in this case +-- since the table in the inner part can be recursively +-- planned SELECT min(r_custkey), max(r_custkey) FROM multi_outer_join_left_hash a RIGHT JOIN multi_outer_join_right_reference b ON (l_custkey = r_custkey); - +SET client_min_messages TO LOG; -- Reverse right join should be same as left join SELECT @@ -279,6 +284,8 @@ WHERE r1.r_custkey is NULL; -- Three way join 2-1-1 (broadcast + broadcast join) should work +-- after #2481 since we're hitting aggressive outer join checks +SET client_min_messages TO DEBUG; SELECT l_custkey, r_custkey, t_custkey FROM @@ -286,6 +293,7 @@ FROM LEFT JOIN multi_outer_join_right_reference r1 ON (l1.l_custkey = r1.r_custkey) LEFT JOIN multi_outer_join_third_reference t1 ON (r1.r_custkey = t1.t_custkey) ORDER BY 1; +SET client_min_messages TO LOG; -- Right join with single shard right most table should error out SELECT diff --git a/src/test/regress/output/multi_outer_join_reference.source b/src/test/regress/output/multi_outer_join_reference.source index ff1270024..c5b8693fc 100644 --- a/src/test/regress/output/multi_outer_join_reference.source +++ b/src/test/regress/output/multi_outer_join_reference.source @@ -198,13 +198,28 @@ FROM 20 | 0 (1 row) --- Right join should be disallowed in this case +SET client_min_messages TO DEBUG1; +-- Right join should be allowed in this case +-- since the table in the inner part can be recursively +-- planned SELECT min(r_custkey), max(r_custkey) FROM multi_outer_join_left_hash a RIGHT JOIN multi_outer_join_right_reference b ON (l_custkey = r_custkey); +<<<<<<< HEAD ERROR: cannot pushdown the subquery DETAIL: There exist a reference table in the outer part of the outer join +======= +LOG: join order: [ "multi_outer_join_left_hash" ] +DEBUG: generating subplan 12_1 for subquery SELECT l_custkey, NULL::character varying(25) AS l_name, NULL::character varying(40) AS l_address, NULL::integer AS l_nationkey, NULL::character(15) AS l_phone, NULL::numeric(15,2) AS l_acctbal, NULL::character(10) AS l_mktsegment, NULL::character varying(117) AS l_comment FROM public.multi_outer_join_left_hash a WHERE true +DEBUG: Plan 12 query after replacing subqueries and CTEs: SELECT min(b.r_custkey) AS min, max(b.r_custkey) AS max FROM ((SELECT intermediate_result.l_custkey, intermediate_result.l_name, intermediate_result.l_address, intermediate_result.l_nationkey, intermediate_result.l_phone, intermediate_result.l_acctbal, intermediate_result.l_mktsegment, intermediate_result.l_comment FROM read_intermediate_result('12_1'::text, 'binary'::citus_copy_format) intermediate_result(l_custkey integer, l_name character varying(25), l_address character varying(40), l_nationkey integer, l_phone character(15), l_acctbal numeric(15,2), l_mktsegment character(10), l_comment character varying(117))) multi_outer_join_left_hash(l_custkey, l_name, l_address, l_nationkey, l_phone, l_acctbal, l_mktsegment, l_comment) RIGHT JOIN public.multi_outer_join_right_reference b ON ((multi_outer_join_left_hash.l_custkey OPERATOR(pg_catalog.=) b.r_custkey))) + min | max +-----+----- + 1 | 15 +(1 row) + +SET client_min_messages TO LOG; +>>>>>>> d9d1dfbf... respect the regression tests for recursively plan inner parts of recurring tuple joins -- Reverse right join should be same as left join SELECT min(l_custkey), max(l_custkey) @@ -313,13 +328,30 @@ FROM 25 | 1 (1 row) --- Right join should not be allowed in this case +SET client_min_messages TO DEBUG; +-- Right join should be allowed in this case +-- since the table in the inner part can be recursively +-- planned SELECT min(r_custkey), max(r_custkey) FROM multi_outer_join_left_hash a RIGHT JOIN multi_outer_join_right_reference b ON (l_custkey = r_custkey); +<<<<<<< HEAD ERROR: cannot pushdown the subquery DETAIL: There exist a reference table in the outer part of the outer join +======= +LOG: join order: [ "multi_outer_join_left_hash" ] +DEBUG: generating subplan 22_1 for subquery SELECT l_custkey, NULL::character varying(25) AS l_name, NULL::character varying(40) AS l_address, NULL::integer AS l_nationkey, NULL::character(15) AS l_phone, NULL::numeric(15,2) AS l_acctbal, NULL::character(10) AS l_mktsegment, NULL::character varying(117) AS l_comment FROM public.multi_outer_join_left_hash a WHERE true +DEBUG: Plan 22 query after replacing subqueries and CTEs: SELECT min(b.r_custkey) AS min, max(b.r_custkey) AS max FROM ((SELECT intermediate_result.l_custkey, intermediate_result.l_name, intermediate_result.l_address, intermediate_result.l_nationkey, intermediate_result.l_phone, intermediate_result.l_acctbal, intermediate_result.l_mktsegment, intermediate_result.l_comment FROM read_intermediate_result('22_1'::text, 'binary'::citus_copy_format) intermediate_result(l_custkey integer, l_name character varying(25), l_address character varying(40), l_nationkey integer, l_phone character(15), l_acctbal numeric(15,2), l_mktsegment character(10), l_comment character varying(117))) multi_outer_join_left_hash(l_custkey, l_name, l_address, l_nationkey, l_phone, l_acctbal, l_mktsegment, l_comment) RIGHT JOIN public.multi_outer_join_right_reference b ON ((multi_outer_join_left_hash.l_custkey OPERATOR(pg_catalog.=) b.r_custkey))) +DEBUG: Creating router plan +DEBUG: Plan is router executable + min | max +-----+----- + 11 | 30 +(1 row) + +SET client_min_messages TO LOG; +>>>>>>> d9d1dfbf... respect the regression tests for recursively plan inner parts of recurring tuple joins -- Reverse right join should be same as left join SELECT min(l_custkey), max(l_custkey) @@ -351,6 +383,8 @@ WHERE r1.r_custkey is NULL; ERROR: complex joins are only supported when all distributed tables are joined on their distribution columns with equal operator -- Three way join 2-1-1 (broadcast + broadcast join) should work +-- after #2481 since we're hitting aggressive outer join checks +SET client_min_messages TO DEBUG; SELECT l_custkey, r_custkey, t_custkey FROM @@ -358,6 +392,7 @@ FROM LEFT JOIN multi_outer_join_right_reference r1 ON (l1.l_custkey = r1.r_custkey) LEFT JOIN multi_outer_join_third_reference t1 ON (r1.r_custkey = t1.t_custkey) ORDER BY 1; +<<<<<<< HEAD l_custkey | r_custkey | t_custkey -----------+-----------+----------- 1 | | @@ -387,6 +422,15 @@ ORDER BY 1; 30 | 30 | 30 (25 rows) +======= +DEBUG: Creating router plan +DEBUG: Plan is router executable +DEBUG: generating subplan 27_1 for subquery SELECT t_custkey, NULL::character varying(25) AS t_name, NULL::character varying(40) AS t_address, NULL::integer AS t_nationkey, NULL::character(15) AS t_phone, NULL::numeric(15,2) AS t_acctbal, NULL::character(10) AS t_mktsegment, NULL::character varying(117) AS t_comment FROM public.multi_outer_join_third_reference t1 WHERE true +DEBUG: Plan 27 query after replacing subqueries and CTEs: SELECT l1.l_custkey, r1.r_custkey, multi_outer_join_third_reference.t_custkey FROM ((public.multi_outer_join_left_hash l1 LEFT JOIN public.multi_outer_join_right_reference r1 ON ((l1.l_custkey OPERATOR(pg_catalog.=) r1.r_custkey))) LEFT JOIN (SELECT intermediate_result.t_custkey, intermediate_result.t_name, intermediate_result.t_address, intermediate_result.t_nationkey, intermediate_result.t_phone, intermediate_result.t_acctbal, intermediate_result.t_mktsegment, intermediate_result.t_comment FROM read_intermediate_result('27_1'::text, 'binary'::citus_copy_format) intermediate_result(t_custkey integer, t_name character varying(25), t_address character varying(40), t_nationkey integer, t_phone character(15), t_acctbal numeric(15,2), t_mktsegment character(10), t_comment character varying(117))) multi_outer_join_third_reference(t_custkey, t_name, t_address, t_nationkey, t_phone, t_acctbal, t_mktsegment, t_comment) ON ((r1.r_custkey OPERATOR(pg_catalog.=) multi_outer_join_third_reference.t_custkey))) ORDER BY l1.l_custkey +ERROR: cannot pushdown the subquery +DETAIL: There exist a reference table in the outer part of the outer join +SET client_min_messages TO LOG; +>>>>>>> d9d1dfbf... respect the regression tests for recursively plan inner parts of recurring tuple joins -- Right join with single shard right most table should error out SELECT l_custkey, r_custkey, t_custkey diff --git a/src/test/regress/sql/multi_dropped_column_aliases.sql b/src/test/regress/sql/multi_dropped_column_aliases.sql index 7e6729351..98020cbb0 100644 --- a/src/test/regress/sql/multi_dropped_column_aliases.sql +++ b/src/test/regress/sql/multi_dropped_column_aliases.sql @@ -26,8 +26,8 @@ SELECT count(*) FROM customer, orders WHERE c_custkey = o_custkey; -- currently not exercised, but we are adding this test to catch this bug when -- we start supporting outer joins. -SELECT c_custkey -FROM (customer LEFT OUTER JOIN orders ON (c_custkey = o_custkey)) AS - test(c_custkey, c_nationkey) - INNER JOIN lineitem ON (test.c_custkey = l_orderkey) -LIMIT 10; +--SELECT c_custkey +--FROM (customer LEFT OUTER JOIN orders ON (c_custkey = o_custkey)) AS + -- test(c_custkey, c_nationkey) + -- INNER JOIN lineitem ON (test.c_custkey = l_orderkey) +--LIMIT 10; diff --git a/src/test/regress/sql/multi_subquery_complex_reference_clause.sql b/src/test/regress/sql/multi_subquery_complex_reference_clause.sql index 169143725..12823fb5d 100644 --- a/src/test/regress/sql/multi_subquery_complex_reference_clause.sql +++ b/src/test/regress/sql/multi_subquery_complex_reference_clause.sql @@ -43,20 +43,29 @@ SELECT subquery_1.user_id FROM ON user_buy_test_table.user_id > users_ref_test_table.id) subquery_1 ORDER BY 1; --- Shouldn't work, reference table at the outer side is not allowed +SET client_min_messages TO DEBUG; + +-- Should work because we can recursively plan the distributed relation on the +-- inner part of the outer join SELECT * FROM - (SELECT random() FROM users_ref_test_table LEFT JOIN user_buy_test_table - ON users_ref_test_table.id = user_buy_test_table.user_id) subquery_1; + (SELECT users_ref_test_table.id FROM users_ref_test_table LEFT JOIN user_buy_test_table + ON users_ref_test_table.id = user_buy_test_table.user_id) subquery_1 ORDER BY 1 DESC; +RESET client_min_messages; -- Should work, reference table at the inner side is allowed SELECT count(*) FROM (SELECT random() FROM users_ref_test_table RIGHT JOIN user_buy_test_table ON user_buy_test_table.user_id = users_ref_test_table.id) subquery_1; --- Shouldn't work, reference table at the outer side is not allowed -SELECT * FROM +SET client_min_messages TO DEBUG; + +-- Should work because we can recursively plan the distributed relation on the +-- inner part of the outer join +SELECT count(*) FROM (SELECT random() FROM user_buy_test_table RIGHT JOIN users_ref_test_table ON user_buy_test_table.user_id = users_ref_test_table.id) subquery_1; +RESET client_min_messages; + -- Equi join test with reference table on non-partition keys SELECT count(*) FROM @@ -167,7 +176,9 @@ SELECT count(*) FROM SELECT count(*) FROM user_buy_test_table LEFT JOIN (SELECT * FROM generate_series(1,10) id) users_ref_test_table ON user_buy_test_table.item_id = users_ref_test_table.id; --- table function cannot be the outer relationship in an outer join +SET client_min_messages TO DEBUG; +-- table function can be the outer relationship in an outer join +-- since the inner side is recursively planned SELECT count(*) FROM (SELECT random() FROM user_buy_test_table RIGHT JOIN generate_series(1,10) AS users_ref_test_table(id) ON user_buy_test_table.item_id > users_ref_test_table.id) subquery_1; @@ -175,6 +186,8 @@ SELECT count(*) FROM SELECT count(*) FROM user_buy_test_table RIGHT JOIN (SELECT * FROM generate_series(1,10) id) users_ref_test_table ON user_buy_test_table.item_id = users_ref_test_table.id; +RESET client_min_messages; + -- volatile functions can be used as table expressions through recursive planning SET client_min_messages TO DEBUG; @@ -209,10 +222,15 @@ ON user_buy_test_table.item_id = users_ref_test_table.id; SELECT count(*) FROM user_buy_test_table LEFT JOIN (SELECT 5 AS id) users_ref_test_table ON user_buy_test_table.item_id = users_ref_test_table.id; --- subquery without FROM cannot be the outer relationship in an outer join +SET client_min_messages TO DEBUG1; + +-- subquery without FROM can be the outer relationship in an outer join +-- since the inner part can be recursively planned SELECT count(*) FROM user_buy_test_table RIGHT JOIN (SELECT 5 AS id) users_ref_test_table ON user_buy_test_table.item_id = users_ref_test_table.id; +RESET client_min_messages; + -- can perform a union with subquery without FROM -- with pulling data to coordinator SET client_min_messages TO DEBUG; @@ -301,8 +319,12 @@ FROM ) as foo GROUP BY user_id ORDER BY 2 DESC LIMIT 10; --- should not be able to pushdown since reference table is in the --- direct outer part of the left join + +SET client_min_messages TO DEBUG1; + +-- although the inner part of an outer join with reference table is +-- recursively planned, we still hit the agressive outer join checks +-- (recurring tuple Left Join recurring tuple) errors SELECT user_id, sum(value_1) FROM @@ -314,13 +336,17 @@ FROM ) as foo GROUP BY user_id ORDER BY 2 DESC LIMIT 10; --- should not be able to pushdown since reference table is in the --- direct outer part of the left join wrapped into a subquery +-- should be able to pushdown since reference table is in the +-- direct outer part of the left join is recursively planned +-- and the final query becomes a router query SELECT - * + users_table.time, users_table.value_2 FROM (SELECT *, random() FROM events_reference_table) as ref_all LEFT JOIN users_table - ON (users_table.user_id = ref_all.value_2); + ON (users_table.user_id = ref_all.value_2) +ORDER BY 1, 2 DESC LIMIT 6; + +RESET client_min_messages; -- should not be able to pushdown since reference table is in the -- outer part of the left join @@ -627,8 +653,9 @@ count(*) AS cnt, "generated_group_field" cnt DESC, generated_group_field ASC LIMIT 10; - -- RIGHT JOINs used with INNER JOINs should error out since reference table exist in the --- right side of the RIGHT JOIN. + -- RIGHT JOINs used with INNER JOINs should work out since reference table exist in the +-- right side of the RIGHT JOIN and the inner subquery is recursively planned +SET client_min_messages TO DEBUG1; SELECT count(*) AS cnt, "generated_group_field" FROM @@ -666,6 +693,8 @@ count(*) AS cnt, "generated_group_field" cnt DESC, generated_group_field ASC LIMIT 10; +RESET client_min_messages; + -- right join where the inner part of the join includes a reference table -- joined with hash partitioned table using non-equi join SELECT user_id, sum(array_length(events_table, 1)), length(hasdone_event), hasdone_event @@ -986,14 +1015,15 @@ INNER JOIN GROUP BY types ORDER BY types; +SET client_min_messages TO DEBUG1; + -- just a sanity check that we don't allow this if the reference table is on the --- left part of the left join +-- left part of the left join, we can still recursively plan the inner side SELECT count(*) FROM (SELECT random() FROM users_ref_test_table LEFT JOIN user_buy_test_table ON user_buy_test_table.item_id > users_ref_test_table.id) subquery_1; -- we do allow non equi join among subqueries via recursive planning -SET client_min_messages TO DEBUG1; SELECT count(*) FROM (SELECT user_buy_test_table.user_id, random() FROM user_buy_test_table LEFT JOIN users_ref_test_table ON user_buy_test_table.item_id > users_ref_test_table.id) subquery_1, diff --git a/src/test/regress/sql/multi_subquery_in_where_reference_clause.sql b/src/test/regress/sql/multi_subquery_in_where_reference_clause.sql index 6f9c74650..4fd6bc7f5 100644 --- a/src/test/regress/sql/multi_subquery_in_where_reference_clause.sql +++ b/src/test/regress/sql/multi_subquery_in_where_reference_clause.sql @@ -38,8 +38,12 @@ GROUP BY user_id ORDER BY user_id LIMIT 3; --- subqueries in WHERE with NOT EXISTS operator, should not work since --- there is a correlated subquery in WHERE clause + +SET client_min_messages TO DEBUG1; + +-- although the subquery in WHERE with NOT EXISTS operator (e.g., semi-join) +-- is correlated with the reference table, since events_table can be +-- recursively planned the whole query becomes a router query SELECT user_id FROM @@ -55,8 +59,10 @@ WHERE ) LIMIT 3; --- immutable functions are also treated as reference tables, query should not --- work since there is a correlated subquery in the WHERE clause +-- immutable functions are also treated as reference tables thus +-- although the subquery in WHERE with NOT EXISTS operator (e.g., semi-join) +-- is correlated with the immutable function, since events_table can be +-- recursively planned the whole query becomes a router query SELECT user_id FROM @@ -70,10 +76,13 @@ WHERE WHERE users_reference_table.user_id = events_table.user_id ) +ORDER BY 1 LIMIT 3; --- subqueries without FROM are also treated as reference tables, query should not --- work since there is a correlated subquery in the WHERE clause +-- subqueries without FROM are also treated as reference tables thus +-- although the subquery in WHERE with NOT EXISTS operator (e.g., semi-join) +-- is correlated with the subquery, since events_table can be +-- recursively planned the whole query becomes a router query SELECT user_id FROM @@ -89,6 +98,8 @@ WHERE ) LIMIT 3; +RESET client_min_messages; + -- join with distributed table prevents FROM from recurring SELECT DISTINCT user_id