diff --git a/src/backend/distributed/planner/query_colocation_checker.c b/src/backend/distributed/planner/query_colocation_checker.c index ed386c7cd..407705820 100644 --- a/src/backend/distributed/planner/query_colocation_checker.c +++ b/src/backend/distributed/planner/query_colocation_checker.c @@ -191,12 +191,16 @@ SubqueryColocated(Query *subquery, ColocatedJoinChecker *checker) /* * There are no relations in the input subquery, such as a subquery * that consist of only intermediate results or without FROM - * clause. + * clause or subquery in WHERE clause anded with FALSE. + * + * Note that for the subquery in WHERE clause, the input original + * subquery (a.k.a., which didn't go through standard_planner()) may + * contain distributed relations, but postgres is smart enough to + * not generate the restriction information. That's the reason for + * not asserting non-existence of distributed relations. */ if (list_length(filteredRestrictionList) == 0) { - Assert(!FindNodeCheck((Node *) subquery, IsDistributedTableRTE)); - return true; } diff --git a/src/test/regress/expected/subquery_in_where.out b/src/test/regress/expected/subquery_in_where.out index 62aefb80d..b15e31bd1 100644 --- a/src/test/regress/expected/subquery_in_where.out +++ b/src/test/regress/expected/subquery_in_where.out @@ -634,6 +634,64 @@ DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT generate_seri 3 (3 rows) +-- non-colocated subquery in WHERE clause ANDed with false +SELECT count(*) +FROM users_Table +WHERE (FALSE AND EXISTS (SELECT * FROM events_table)); + count +--------------------------------------------------------------------- + 0 +(1 row) + +-- multiple non-colocated subqueries in WHERE clause ANDed with false +SELECT count(*) +FROM users_Table +WHERE value_1 IN + (SELECT value_1 + FROM users_Table) OR (FALSE AND EXISTS (SELECT * FROM events_table)); +DEBUG: generating subplan XXX_1 for subquery SELECT value_1 FROM public.users_table +DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT count(*) AS count FROM public.users_table WHERE ((value_1 OPERATOR(pg_catalog.=) ANY (SELECT intermediate_result.value_1 FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(value_1 integer))) OR (false AND (EXISTS (SELECT events_table.user_id, events_table."time", events_table.event_type, events_table.value_2, events_table.value_3, events_table.value_4 FROM public.events_table)))) + count +--------------------------------------------------------------------- + 101 +(1 row) + +-- multiple non-colocated subqueries in WHERE clause ANDed with false +SELECT count(*) +FROM users_Table +WHERE value_1 IN + (SELECT value_1 + FROM users_Table) AND (FALSE AND EXISTS (SELECT * FROM events_table)); + count +--------------------------------------------------------------------- + 0 +(1 row) + +-- non-colocated subquery in WHERE clause ANDed with true +SELECT count(*) +FROM users_Table +WHERE (TRUE AND EXISTS (SELECT * FROM events_table)); +DEBUG: generating subplan XXX_1 for subquery SELECT user_id, "time", event_type, value_2, value_3, value_4 FROM public.events_table +DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT count(*) AS count FROM public.users_table WHERE (true AND (EXISTS (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('XXX_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)))) + count +--------------------------------------------------------------------- + 101 +(1 row) + +-- multiple non-colocated subqueries in WHERE clause ANDed with true +SELECT count(*) +FROM users_Table +WHERE value_1 IN + (SELECT value_1 + FROM users_Table) OR (EXISTS (SELECT * FROM events_table)); +DEBUG: generating subplan XXX_1 for subquery SELECT value_1 FROM public.users_table +DEBUG: generating subplan XXX_2 for subquery SELECT user_id, "time", event_type, value_2, value_3, value_4 FROM public.events_table +DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT count(*) AS count FROM public.users_table WHERE ((value_1 OPERATOR(pg_catalog.=) ANY (SELECT intermediate_result.value_1 FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(value_1 integer))) OR (EXISTS (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('XXX_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)))) + count +--------------------------------------------------------------------- + 101 +(1 row) + -- Local tables also planned recursively, so using it as part of the FROM clause -- make the clause recurring CREATE TABLE local_table(id int, value_1 int); diff --git a/src/test/regress/sql/subquery_in_where.sql b/src/test/regress/sql/subquery_in_where.sql index df637ce19..884307845 100644 --- a/src/test/regress/sql/subquery_in_where.sql +++ b/src/test/regress/sql/subquery_in_where.sql @@ -471,6 +471,37 @@ IN ORDER BY generate_series ASC; +-- non-colocated subquery in WHERE clause ANDed with false +SELECT count(*) +FROM users_Table +WHERE (FALSE AND EXISTS (SELECT * FROM events_table)); + +-- multiple non-colocated subqueries in WHERE clause ANDed with false +SELECT count(*) +FROM users_Table +WHERE value_1 IN + (SELECT value_1 + FROM users_Table) OR (FALSE AND EXISTS (SELECT * FROM events_table)); + +-- multiple non-colocated subqueries in WHERE clause ANDed with false +SELECT count(*) +FROM users_Table +WHERE value_1 IN + (SELECT value_1 + FROM users_Table) AND (FALSE AND EXISTS (SELECT * FROM events_table)); + +-- non-colocated subquery in WHERE clause ANDed with true +SELECT count(*) +FROM users_Table +WHERE (TRUE AND EXISTS (SELECT * FROM events_table)); + +-- multiple non-colocated subqueries in WHERE clause ANDed with true +SELECT count(*) +FROM users_Table +WHERE value_1 IN + (SELECT value_1 + FROM users_Table) OR (EXISTS (SELECT * FROM events_table)); + -- Local tables also planned recursively, so using it as part of the FROM clause -- make the clause recurring CREATE TABLE local_table(id int, value_1 int);