diff --git a/src/backend/distributed/planner/multi_logical_planner.c b/src/backend/distributed/planner/multi_logical_planner.c index 05550ed28..91cdd76bb 100644 --- a/src/backend/distributed/planner/multi_logical_planner.c +++ b/src/backend/distributed/planner/multi_logical_planner.c @@ -90,7 +90,6 @@ static bool ExtractSetOperationStatmentWalker(Node *node, List **setOperationLis static DeferredErrorMessage * DeferErrorIfUnsupportedTableCombination(Query *queryTree); static bool WindowPartitionOnDistributionColumn(Query *query); static bool AllTargetExpressionsAreColumnReferences(List *targetEntryList); -static bool IsDistributedTableRTE(Node *node); static FieldSelect * CompositeFieldRecursive(Expr *expression, Query *query); static bool FullCompositeFieldList(List *compositeFieldList); static MultiNode * MultiNodeTree(Query *queryTree); @@ -657,7 +656,8 @@ DeferErrorIfFromClauseRecurs(Query *queryTree) "cannot pushdown the subquery", "Reference tables are not allowed in FROM " "clause when the query has subqueries in " - "WHERE clause", NULL); + "WHERE clause and it references a column " + "from another query", NULL); } else if (recurType == RECURRING_TUPLES_FUNCTION) { @@ -665,7 +665,8 @@ DeferErrorIfFromClauseRecurs(Query *queryTree) "cannot pushdown the subquery", "Functions are not allowed in FROM " "clause when the query has subqueries in " - "WHERE clause", NULL); + "WHERE clause and it references a column " + "from another query", NULL); } else if (recurType == RECURRING_TUPLES_RESULT_FUNCTION) { @@ -673,7 +674,8 @@ DeferErrorIfFromClauseRecurs(Query *queryTree) "cannot pushdown the subquery", "Complex subqueries and CTEs are not allowed in " "the FROM clause when the query has subqueries in the " - "WHERE clause", NULL); + "WHERE clause and it references a column " + "from another query", NULL); } else if (recurType == RECURRING_TUPLES_EMPTY_JOIN_TREE) { @@ -681,7 +683,8 @@ DeferErrorIfFromClauseRecurs(Query *queryTree) "cannot pushdown the subquery", "Subqueries without FROM are not allowed in FROM " "clause when the outer query has subqueries in " - "WHERE clause", NULL); + "WHERE clause and it references a column " + "from another query", NULL); } /* @@ -1330,7 +1333,7 @@ QueryContainsDistributedTableRTE(Query *query) * is a range table relation entry that points to a distributed * relation (i.e., excluding reference tables). */ -static bool +bool IsDistributedTableRTE(Node *node) { RangeTblEntry *rangeTableEntry = NULL; diff --git a/src/backend/distributed/planner/recursive_planning.c b/src/backend/distributed/planner/recursive_planning.c index fd5797701..5b55afce2 100644 --- a/src/backend/distributed/planner/recursive_planning.c +++ b/src/backend/distributed/planner/recursive_planning.c @@ -115,6 +115,9 @@ typedef struct VarLevelsUpWalkerContext static DeferredErrorMessage * RecursivelyPlanSubqueriesAndCTEs(Query *query, RecursivePlanningContext * context); +static bool ShouldRecursivelyPlanAllSubqueriesInWhere(Query *query); +static bool RecursivelyPlanAllSubqueries(Node *node, + RecursivePlanningContext *planningContext); static DeferredErrorMessage * RecursivelyPlanCTEs(Query *query, RecursivePlanningContext *context); static bool RecursivelyPlanSubqueryWalker(Node *node, RecursivePlanningContext *context); @@ -238,10 +241,85 @@ RecursivelyPlanSubqueriesAndCTEs(Query *query, RecursivePlanningContext *context RecursivelyPlanSetOperations(query, (Node *) query->setOperations, context); } + /* + * If the FROM clause is recurring (does not contain a distributed table), + * then we cannot have any distributed tables appearing in subqueries in + * the WHERE clause. + */ + if (ShouldRecursivelyPlanAllSubqueriesInWhere(query)) + { + /* replace all subqueries in the WHERE clause */ + RecursivelyPlanAllSubqueries((Node *) query->jointree->quals, context); + } + return NULL; } +/* + * ShouldRecursivelyPlanAllSubqueriesInWhere returns true if the query has + * a WHERE clause and a recurring FROM clause (does not contain a distributed + * table). + */ +static bool +ShouldRecursivelyPlanAllSubqueriesInWhere(Query *query) +{ + FromExpr *joinTree = NULL; + Node *whereClause = NULL; + + joinTree = query->jointree; + if (joinTree == NULL) + { + /* there is no FROM clause */ + return false; + } + + whereClause = joinTree->quals; + if (whereClause == NULL) + { + /* there is no WHERE clause */ + return false; + } + + if (FindNodeCheckInRangeTableList(query->rtable, IsDistributedTableRTE)) + { + /* there is a distributed table in the FROM clause */ + return false; + } + + return true; +} + + +/* + * RecursivelyPlanAllSubqueries descends into an expression tree and recursively + * plans all subqueries that contain at least one distributed table. The recursive + * planning starts from the top of the input query. + */ +static bool +RecursivelyPlanAllSubqueries(Node *node, RecursivePlanningContext *planningContext) +{ + if (node == NULL) + { + return false; + } + + if (IsA(node, Query)) + { + Query *query = (Query *) node; + + if (FindNodeCheckInRangeTableList(query->rtable, IsDistributedTableRTE)) + { + RecursivelyPlanSubquery(query, planningContext); + } + + return false; + } + + return expression_tree_walker(node, RecursivelyPlanAllSubqueries, planningContext); +} + + /* * RecursivelyPlanCTEs plans all CTEs in the query by recursively calling the planner * The resulting plan is added to planningContext->subPlanList and CTE references diff --git a/src/include/distributed/multi_logical_planner.h b/src/include/distributed/multi_logical_planner.h index 08f8cc2f5..f5748a374 100644 --- a/src/include/distributed/multi_logical_planner.h +++ b/src/include/distributed/multi_logical_planner.h @@ -195,6 +195,7 @@ extern DeferredErrorMessage * DeferErrorIfUnsupportedUnionQuery(Query *queryTree extern bool SafeToPushdownWindowFunction(Query *query, StringInfo *errorDetail); extern bool TargetListOnPartitionColumn(Query *query, List *targetEntryList); extern bool FindNodeCheckInRangeTableList(List *rtable, bool (*check)(Node *)); +extern bool IsDistributedTableRTE(Node *node); extern bool QueryContainsDistributedTableRTE(Query *query); extern bool ContainsReadIntermediateResultFunction(Node *node); extern MultiNode * ParentNode(MultiNode *multiNode); 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 18eaba1fe..c95626774 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,8 @@ LIMIT 3; --------- (0 rows) --- subqueries in WHERE with NOT EXISTS operator, should not work --- there is a reference table in the outer part of the join +-- subqueries in WHERE with NOT EXISTS operator, should not work since +-- there is a correlated subquery in WHERE clause SELECT user_id FROM @@ -63,8 +63,9 @@ WHERE ) LIMIT 3; ERROR: cannot pushdown the subquery -DETAIL: Reference tables are not allowed in FROM clause when the query has subqueries in WHERE clause --- immutable functions are also treated as reference tables +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 SELECT user_id FROM @@ -80,8 +81,9 @@ WHERE ) LIMIT 3; ERROR: cannot pushdown the subquery -DETAIL: Functions are not allowed in FROM clause when the query has subqueries in WHERE clause --- subqueries without FROM are also treated as reference tables +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 SELECT user_id FROM @@ -97,7 +99,7 @@ WHERE ) 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 +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 -- join with distributed table prevents FROM from recurring SELECT DISTINCT user_id @@ -413,7 +415,9 @@ ORDER BY 1, 2; 5 | 5 (2 rows) --- reference tables are not allowed if there is sublink +-- change debug level to check recursive planning output +SET client_min_messages TO DEBUG1; +-- recursively planning subqueries in WHERE clause due to recurring table in FROM SELECT count(*) FROM @@ -421,9 +425,14 @@ 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); -ERROR: cannot pushdown the subquery -DETAIL: Reference tables are not allowed in FROM clause when the query has subqueries in WHERE clause --- reference tables are not allowed if there is sublink +DEBUG: generating subplan 16_1 for subquery SELECT users_table.value_2 FROM (public.users_table JOIN public.users_reference_table u2 ON ((users_table.value_2 = u2.value_2))) +DEBUG: Plan 16 query after replacing subqueries and CTEs: SELECT count(*) AS count FROM public.users_reference_table WHERE (NOT (user_id IN (SELECT intermediate_result.value_2 FROM read_intermediate_result('16_1'::text, 'binary'::citus_copy_format) intermediate_result(value_2 integer)))) + count +------- + 10 +(1 row) + +-- recursively planning subqueries in WHERE clause due to recurring table in FROM SELECT count(*) FROM (SELECT @@ -432,9 +441,14 @@ FROM (SELECT users_table.value_2 FROM users_table JOIN users_reference_table AS u2 ON users_table.value_2 = u2.value_2); -ERROR: cannot pushdown the subquery -DETAIL: Reference tables are not allowed in FROM clause when the query has subqueries in WHERE clause --- reference tables are not allowed if there is sublink +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 = u2.value_2))) +DEBUG: Plan 18 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 IN (SELECT intermediate_result.value_2 FROM read_intermediate_result('18_1'::text, 'binary'::citus_copy_format) intermediate_result(value_2 integer)))) + count +------- + 10 +(1 row) + +-- query should not work since there is a correlated subquery in the WHERE clause SELECT user_id, count(*) FROM users_reference_table @@ -449,9 +463,8 @@ ORDER BY 2 DESC, 1 DESC LIMIT 5; ERROR: cannot pushdown the subquery -DETAIL: Reference tables are not allowed in FROM clause when the query has subqueries in WHERE clause --- reference tables are not allowed if there is sublink --- this time in 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 +-- query will be planned as a SEMI JOIN SELECT * FROM users_table WHERE user_id IN @@ -463,6 +476,7 @@ WHERE user_id IN FROM users_reference_table AS u2)) ORDER BY 1,2,3 LIMIT 5; +DEBUG: push down of limit count: 5 user_id | time | value_1 | value_2 | value_3 | value_4 ---------+---------------------------------+---------+---------+---------+--------- 1 | Wed Nov 22 22:51:43.132261 2017 | 4 | 0 | 3 | @@ -472,6 +486,7 @@ LIMIT 5; 1 | Thu Nov 23 11:44:57.515981 2017 | 4 | 3 | 4 | (5 rows) +SET client_min_messages TO DEFAULT; -- not supported since GROUP BY references to an upper level query SELECT user_id 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 12b6fbb87..42113d061 100644 --- a/src/test/regress/expected/set_operation_and_local_tables.out +++ b/src/test/regress/expected/set_operation_and_local_tables.out @@ -260,11 +260,26 @@ DEBUG: Plan 45 query after replacing subqueries and CTEs: SELECT u.x, u.y, test ---+---+--- (0 rows) --- distributed table in WHERE clause, but not FROM clause still disallowed +-- 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 -ERROR: cannot pushdown the subquery -DETAIL: Complex subqueries and CTEs are not allowed in the FROM clause when the query has subqueries in the WHERE clause +DEBUG: generating subplan 48_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 IN (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: 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: Creating router plan +DEBUG: Plan is router executable + x +--- + 1 + 2 +(2 rows) + SET citus.enable_repartition_joins TO ON; -- repartition is recursively planned before the set operation (SELECT x FROM test) INTERSECT (SELECT t1.x FROM test as t1, test as t2 WHERE t1.x = t2.y LIMIT 2) INTERSECT (((SELECT x FROM local_test) UNION ALL (SELECT x FROM test)) INTERSECT (SELECT i FROM generate_series(0, 100) i)) ORDER BY 1 DESC; @@ -299,11 +314,11 @@ DEBUG: pruning merge fetch taskId 11 DETAIL: Creating dependency on merge taskId 24 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 50_1 for subquery SELECT t1.x FROM recursive_set_local.test t1, recursive_set_local.test t2 WHERE (t1.x = t2.y) LIMIT 2 -DEBUG: generating subplan 50_2 for subquery SELECT x FROM recursive_set_local.local_test -DEBUG: generating subplan 50_3 for subquery SELECT x FROM recursive_set_local.test -DEBUG: generating subplan 50_4 for subquery SELECT x FROM recursive_set_local.test -DEBUG: Plan 50 query after replacing subqueries and CTEs: SELECT intermediate_result.x FROM read_intermediate_result('50_3'::text, 'binary'::citus_copy_format) intermediate_result(x integer) INTERSECT SELECT intermediate_result.x FROM read_intermediate_result('50_1'::text, 'binary'::citus_copy_format) intermediate_result(x integer) INTERSECT ((SELECT intermediate_result.x FROM read_intermediate_result('50_2'::text, 'binary'::citus_copy_format) intermediate_result(x integer) UNION ALL SELECT intermediate_result.x FROM read_intermediate_result('50_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 53_1 for subquery SELECT t1.x FROM recursive_set_local.test t1, recursive_set_local.test t2 WHERE (t1.x = 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: 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 e93e68a35..9d53a7d50 100644 --- a/src/test/regress/expected/set_operations.out +++ b/src/test/regress/expected/set_operations.out @@ -549,24 +549,31 @@ DEBUG: Plan is router executable 2 | 2 (2 rows) --- set operations are recursively planned and not the sublink, thus should error out +-- set operations and the sublink can be recursively planned SELECT * FROM ((SELECT x,y FROM test) UNION (SELECT y,x FROM test)) foo WHERE x IN (SELECT y FROM test) ORDER BY 1; DEBUG: generating subplan 112_1 for subquery SELECT x, y FROM recursive_union.test DEBUG: generating subplan 112_2 for subquery SELECT y, x FROM recursive_union.test DEBUG: Creating router plan DEBUG: Plan is router executable DEBUG: generating subplan 112_3 for subquery SELECT intermediate_result.x, intermediate_result.y FROM read_intermediate_result('112_1'::text, 'binary'::citus_copy_format) intermediate_result(x integer, y integer) UNION SELECT intermediate_result.y, intermediate_result.x FROM read_intermediate_result('112_2'::text, 'binary'::citus_copy_format) intermediate_result(y integer, x integer) -DEBUG: Plan 112 query after replacing subqueries and CTEs: SELECT x, y FROM (SELECT intermediate_result.x, intermediate_result.y FROM read_intermediate_result('112_3'::text, 'binary'::citus_copy_format) intermediate_result(x integer, y integer)) foo WHERE (x IN (SELECT test.y FROM recursive_union.test)) ORDER BY x -ERROR: cannot pushdown the subquery -DETAIL: Complex subqueries and CTEs are not allowed in the FROM clause when the query has subqueries in the WHERE clause +DEBUG: generating subplan 112_4 for subquery SELECT y FROM recursive_union.test +DEBUG: Plan 112 query after replacing subqueries and CTEs: SELECT x, y FROM (SELECT intermediate_result.x, intermediate_result.y FROM read_intermediate_result('112_3'::text, 'binary'::citus_copy_format) intermediate_result(x integer, y integer)) foo WHERE (x IN (SELECT intermediate_result.y FROM read_intermediate_result('112_4'::text, 'binary'::citus_copy_format) intermediate_result(y integer))) ORDER BY x +DEBUG: Creating router plan +DEBUG: Plan is router executable + x | y +---+--- + 1 | 1 + 2 | 2 +(2 rows) + -- set operations works fine with pushdownable window functions SELECT x, y, rnk FROM (SELECT *, rank() OVER my_win as rnk FROM test WINDOW my_win AS (PARTITION BY x ORDER BY y DESC)) as foo UNION SELECT x, y, rnk FROM (SELECT *, rank() OVER my_win as rnk FROM test WINDOW my_win AS (PARTITION BY x ORDER BY y DESC)) as bar ORDER BY 1 DESC, 2 DESC, 3 DESC; -DEBUG: generating subplan 116_1 for subquery SELECT x, y, rnk FROM (SELECT test.x, test.y, rank() OVER my_win AS rnk FROM recursive_union.test WINDOW my_win AS (PARTITION BY test.x ORDER BY test.y DESC)) foo -DEBUG: generating subplan 116_2 for subquery SELECT x, y, rnk FROM (SELECT test.x, test.y, rank() OVER my_win AS rnk FROM recursive_union.test WINDOW my_win AS (PARTITION BY test.x ORDER BY test.y DESC)) bar -DEBUG: Plan 116 query after replacing subqueries and CTEs: SELECT intermediate_result.x, intermediate_result.y, intermediate_result.rnk FROM read_intermediate_result('116_1'::text, 'binary'::citus_copy_format) intermediate_result(x integer, y integer, rnk bigint) UNION SELECT intermediate_result.x, intermediate_result.y, intermediate_result.rnk FROM read_intermediate_result('116_2'::text, 'binary'::citus_copy_format) intermediate_result(x integer, y integer, rnk bigint) ORDER BY 1 DESC, 2 DESC, 3 DESC +DEBUG: generating subplan 117_1 for subquery SELECT x, y, rnk FROM (SELECT test.x, test.y, rank() OVER my_win AS rnk FROM recursive_union.test WINDOW my_win AS (PARTITION BY test.x ORDER BY test.y DESC)) foo +DEBUG: generating subplan 117_2 for subquery SELECT x, y, rnk FROM (SELECT test.x, test.y, rank() OVER my_win AS rnk FROM recursive_union.test WINDOW my_win AS (PARTITION BY test.x ORDER BY test.y DESC)) bar +DEBUG: Plan 117 query after replacing subqueries and CTEs: SELECT intermediate_result.x, intermediate_result.y, intermediate_result.rnk FROM read_intermediate_result('117_1'::text, 'binary'::citus_copy_format) intermediate_result(x integer, y integer, rnk bigint) UNION SELECT intermediate_result.x, intermediate_result.y, intermediate_result.rnk FROM read_intermediate_result('117_2'::text, 'binary'::citus_copy_format) intermediate_result(x integer, y integer, rnk bigint) ORDER BY 1 DESC, 2 DESC, 3 DESC DEBUG: Creating router plan DEBUG: Plan is router executable x | y | rnk @@ -584,12 +591,12 @@ HINT: Window functions are supported in two ways. Either add an equality filter -- other set operations in joins also cannot be pushed down SELECT * FROM ((SELECT * FROM test) EXCEPT (SELECT * FROM test ORDER BY x LIMIT 1)) u JOIN test USING (x) ORDER BY 1,2; DEBUG: push down of limit count: 1 -DEBUG: generating subplan 121_1 for subquery SELECT x, y FROM recursive_union.test ORDER BY x LIMIT 1 -DEBUG: generating subplan 121_2 for subquery SELECT x, y FROM recursive_union.test +DEBUG: generating subplan 122_1 for subquery SELECT x, y FROM recursive_union.test ORDER BY x LIMIT 1 +DEBUG: generating subplan 122_2 for subquery SELECT x, y FROM recursive_union.test DEBUG: Creating router plan DEBUG: Plan is router executable -DEBUG: generating subplan 121_3 for subquery SELECT intermediate_result.x, intermediate_result.y FROM read_intermediate_result('121_2'::text, 'binary'::citus_copy_format) intermediate_result(x integer, y integer) EXCEPT SELECT intermediate_result.x, intermediate_result.y FROM read_intermediate_result('121_1'::text, 'binary'::citus_copy_format) intermediate_result(x integer, y integer) -DEBUG: Plan 121 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('121_3'::text, 'binary'::citus_copy_format) intermediate_result(x integer, y integer)) u JOIN recursive_union.test USING (x)) ORDER BY u.x, u.y +DEBUG: generating subplan 122_3 for subquery SELECT intermediate_result.x, intermediate_result.y FROM read_intermediate_result('122_2'::text, 'binary'::citus_copy_format) intermediate_result(x integer, y integer) EXCEPT SELECT intermediate_result.x, intermediate_result.y FROM read_intermediate_result('122_1'::text, 'binary'::citus_copy_format) intermediate_result(x integer, y integer) +DEBUG: Plan 122 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('122_3'::text, 'binary'::citus_copy_format) intermediate_result(x integer, y integer)) u JOIN recursive_union.test USING (x)) ORDER BY u.x, u.y x | y | y ---+---+--- 2 | 2 | 2 @@ -597,18 +604,33 @@ DEBUG: Plan 121 query after replacing subqueries and CTEs: SELECT u.x, u.y, tes SELECT * FROM ((SELECT * FROM test) INTERSECT (SELECT * FROM test ORDER BY x LIMIT 1)) u LEFT JOIN test USING (x) ORDER BY 1,2; DEBUG: push down of limit count: 1 -DEBUG: generating subplan 125_1 for subquery SELECT x, y FROM recursive_union.test ORDER BY x LIMIT 1 -DEBUG: generating subplan 125_2 for subquery SELECT x, y FROM recursive_union.test +DEBUG: generating subplan 126_1 for subquery SELECT x, y FROM recursive_union.test ORDER BY x LIMIT 1 +DEBUG: generating subplan 126_2 for subquery SELECT x, y FROM recursive_union.test DEBUG: Creating router plan DEBUG: Plan is router executable -DEBUG: generating subplan 125_3 for subquery SELECT intermediate_result.x, intermediate_result.y FROM read_intermediate_result('125_2'::text, 'binary'::citus_copy_format) intermediate_result(x integer, y integer) INTERSECT SELECT intermediate_result.x, intermediate_result.y FROM read_intermediate_result('125_1'::text, 'binary'::citus_copy_format) intermediate_result(x integer, y integer) -DEBUG: Plan 125 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('125_3'::text, 'binary'::citus_copy_format) intermediate_result(x integer, y integer)) u LEFT JOIN recursive_union.test USING (x)) ORDER BY u.x, u.y +DEBUG: generating subplan 126_3 for subquery SELECT intermediate_result.x, intermediate_result.y FROM read_intermediate_result('126_2'::text, 'binary'::citus_copy_format) intermediate_result(x integer, y integer) INTERSECT SELECT intermediate_result.x, intermediate_result.y FROM read_intermediate_result('126_1'::text, 'binary'::citus_copy_format) intermediate_result(x integer, y integer) +DEBUG: Plan 126 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('126_3'::text, 'binary'::citus_copy_format) intermediate_result(x integer, y integer)) u LEFT JOIN recursive_union.test 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 --- distributed table in WHERE clause, but not FROM clause still disallowed +-- distributed table in WHERE clause is recursively planned SELECT * FROM ((SELECT * FROM test) UNION (SELECT * FROM ref WHERE a IN (SELECT x FROM test))) u ORDER BY 1,2; -ERROR: cannot pushdown the subquery -DETAIL: Reference tables are not allowed in FROM clause when the query has subqueries in WHERE clause +DEBUG: generating subplan 130_1 for subquery SELECT x FROM recursive_union.test +DEBUG: Creating router plan +DEBUG: Plan is router executable +DEBUG: generating subplan 130_2 for subquery SELECT a, b FROM recursive_union.ref WHERE (a IN (SELECT intermediate_result.x FROM read_intermediate_result('130_1'::text, 'binary'::citus_copy_format) intermediate_result(x integer))) +DEBUG: generating subplan 130_3 for subquery SELECT x, y FROM recursive_union.test +DEBUG: Creating router plan +DEBUG: Plan is router executable +DEBUG: generating subplan 130_4 for subquery SELECT intermediate_result.x, intermediate_result.y FROM read_intermediate_result('130_3'::text, 'binary'::citus_copy_format) intermediate_result(x integer, y integer) UNION SELECT intermediate_result.a, intermediate_result.b FROM read_intermediate_result('130_2'::text, 'binary'::citus_copy_format) intermediate_result(a integer, b integer) +DEBUG: Plan 130 query after replacing subqueries and CTEs: SELECT x, y FROM (SELECT intermediate_result.x, intermediate_result.y FROM read_intermediate_result('130_4'::text, 'binary'::citus_copy_format) intermediate_result(x integer, y integer)) u ORDER BY x, y +DEBUG: Creating router plan +DEBUG: Plan is router executable + x | y +---+--- + 1 | 1 + 2 | 2 +(2 rows) + -- subquery union in WHERE clause with partition column equality and implicit join is pushed down SELECT * FROM test a WHERE x IN (SELECT x FROM test b WHERE y = 1 UNION SELECT x FROM test c WHERE y = 2) ORDER BY 1,2; x | y @@ -622,12 +644,12 @@ SELECT * FROM test a WHERE x NOT IN (SELECT x FROM test b WHERE y = 1 UNION SELE ERROR: complex joins are only supported when all distributed tables are joined on their distribution columns with equal operator -- subquery union in WHERE clause without parition column equality is recursively planned SELECT * FROM test a WHERE x IN (SELECT x FROM test b UNION SELECT y FROM test c) ORDER BY 1,2; -DEBUG: generating subplan 133_1 for subquery SELECT x FROM recursive_union.test b -DEBUG: generating subplan 133_2 for subquery SELECT y FROM recursive_union.test c +DEBUG: generating subplan 137_1 for subquery SELECT x FROM recursive_union.test b +DEBUG: generating subplan 137_2 for subquery SELECT y FROM recursive_union.test c DEBUG: Creating router plan DEBUG: Plan is router executable -DEBUG: generating subplan 133_3 for subquery SELECT intermediate_result.x FROM read_intermediate_result('133_1'::text, 'binary'::citus_copy_format) intermediate_result(x integer) UNION SELECT intermediate_result.y FROM read_intermediate_result('133_2'::text, 'binary'::citus_copy_format) intermediate_result(y integer) -DEBUG: Plan 133 query after replacing subqueries and CTEs: SELECT x, y FROM recursive_union.test a WHERE (x IN (SELECT intermediate_result.x FROM read_intermediate_result('133_3'::text, 'binary'::citus_copy_format) intermediate_result(x integer))) ORDER BY x, y +DEBUG: generating subplan 137_3 for subquery SELECT intermediate_result.x FROM read_intermediate_result('137_1'::text, 'binary'::citus_copy_format) intermediate_result(x integer) UNION SELECT intermediate_result.y FROM read_intermediate_result('137_2'::text, 'binary'::citus_copy_format) intermediate_result(y integer) +DEBUG: Plan 137 query after replacing subqueries and CTEs: SELECT x, y FROM recursive_union.test a WHERE (x IN (SELECT intermediate_result.x FROM read_intermediate_result('137_3'::text, 'binary'::citus_copy_format) intermediate_result(x integer))) ORDER BY x, y x | y ---+--- 1 | 1 @@ -636,22 +658,22 @@ DEBUG: Plan 133 query after replacing subqueries and CTEs: SELECT x, y FROM rec -- correlated subquery with union in WHERE clause SELECT * FROM test a WHERE x IN (SELECT x FROM test b UNION SELECT y FROM test c WHERE a.x = c.x) ORDER BY 1,2; -DEBUG: generating subplan 137_1 for subquery SELECT x FROM recursive_union.test b +DEBUG: generating subplan 141_1 for subquery SELECT x FROM recursive_union.test b DEBUG: skipping recursive planning for the subquery since it contains references to outer queries DEBUG: skipping recursive planning for the subquery since it contains references to outer queries -DEBUG: Plan 137 query after replacing subqueries and CTEs: SELECT x, y FROM recursive_union.test a WHERE (x IN (SELECT intermediate_result.x FROM read_intermediate_result('137_1'::text, 'binary'::citus_copy_format) intermediate_result(x integer) UNION SELECT c.y FROM recursive_union.test c WHERE (a.x = c.x))) ORDER BY x, y +DEBUG: Plan 141 query after replacing subqueries and CTEs: SELECT x, y FROM recursive_union.test a WHERE (x IN (SELECT intermediate_result.x FROM read_intermediate_result('141_1'::text, 'binary'::citus_copy_format) intermediate_result(x integer) UNION SELECT c.y FROM recursive_union.test c WHERE (a.x = c.x))) ORDER BY x, y DEBUG: skipping recursive planning for the subquery since it contains references to outer queries DEBUG: skipping recursive planning for the subquery since it contains references to outer queries ERROR: complex joins are only supported when all distributed tables are joined on their distribution columns with equal operator -- force unions to be planned while subqueries are being planned SELECT * FROM ((SELECT * FROM test) UNION (SELECT * FROM test) ORDER BY 1,2 LIMIT 5) as foo ORDER BY 1 DESC LIMIT 3; -DEBUG: generating subplan 140_1 for subquery SELECT x, y FROM recursive_union.test -DEBUG: generating subplan 140_2 for subquery SELECT x, y FROM recursive_union.test -DEBUG: Plan 140 query after replacing subqueries and CTEs: SELECT intermediate_result.x, intermediate_result.y FROM read_intermediate_result('140_1'::text, 'binary'::citus_copy_format) intermediate_result(x integer, y integer) UNION SELECT intermediate_result.x, intermediate_result.y FROM read_intermediate_result('140_2'::text, 'binary'::citus_copy_format) intermediate_result(x integer, y integer) ORDER BY 1, 2 LIMIT 5 +DEBUG: generating subplan 144_1 for subquery SELECT x, y FROM recursive_union.test +DEBUG: generating subplan 144_2 for subquery SELECT x, y FROM recursive_union.test +DEBUG: Plan 144 query after replacing subqueries and CTEs: SELECT intermediate_result.x, intermediate_result.y FROM read_intermediate_result('144_1'::text, 'binary'::citus_copy_format) intermediate_result(x integer, y integer) UNION SELECT intermediate_result.x, intermediate_result.y FROM read_intermediate_result('144_2'::text, 'binary'::citus_copy_format) intermediate_result(x integer, y integer) ORDER BY 1, 2 LIMIT 5 DEBUG: Creating router plan DEBUG: Plan is router executable -DEBUG: generating subplan 139_1 for subquery SELECT test.x, test.y FROM recursive_union.test UNION SELECT test.x, test.y FROM recursive_union.test ORDER BY 1, 2 LIMIT 5 -DEBUG: Plan 139 query after replacing subqueries and CTEs: SELECT x, y FROM (SELECT intermediate_result.x, intermediate_result.y FROM read_intermediate_result('139_1'::text, 'binary'::citus_copy_format) intermediate_result(x integer, y integer)) foo ORDER BY x DESC LIMIT 3 +DEBUG: generating subplan 143_1 for subquery SELECT test.x, test.y FROM recursive_union.test UNION SELECT test.x, test.y FROM recursive_union.test ORDER BY 1, 2 LIMIT 5 +DEBUG: Plan 143 query after replacing subqueries and CTEs: SELECT x, y FROM (SELECT intermediate_result.x, intermediate_result.y FROM read_intermediate_result('143_1'::text, 'binary'::citus_copy_format) intermediate_result(x integer, y integer)) foo ORDER BY x DESC LIMIT 3 DEBUG: Creating router plan DEBUG: Plan is router executable x | y @@ -662,12 +684,12 @@ DEBUG: Plan is router executable -- distinct and count distinct should work without any problems select count(DISTINCT t.x) FROM ((SELECT DISTINCT x FROM test) UNION (SELECT DISTINCT y FROM test)) as t(x) ORDER BY 1; -DEBUG: generating subplan 143_1 for subquery SELECT DISTINCT y FROM recursive_union.test -DEBUG: generating subplan 143_2 for subquery SELECT DISTINCT x FROM recursive_union.test +DEBUG: generating subplan 147_1 for subquery SELECT DISTINCT y FROM recursive_union.test +DEBUG: generating subplan 147_2 for subquery SELECT DISTINCT x FROM recursive_union.test DEBUG: Creating router plan DEBUG: Plan is router executable -DEBUG: generating subplan 143_3 for subquery SELECT intermediate_result.x FROM read_intermediate_result('143_2'::text, 'binary'::citus_copy_format) intermediate_result(x integer) UNION SELECT intermediate_result.y FROM read_intermediate_result('143_1'::text, 'binary'::citus_copy_format) intermediate_result(y integer) -DEBUG: Plan 143 query after replacing subqueries and CTEs: SELECT count(DISTINCT x) AS count FROM (SELECT intermediate_result.x FROM read_intermediate_result('143_3'::text, 'binary'::citus_copy_format) intermediate_result(x integer)) t(x) ORDER BY (count(DISTINCT x)) +DEBUG: generating subplan 147_3 for subquery SELECT intermediate_result.x FROM read_intermediate_result('147_2'::text, 'binary'::citus_copy_format) intermediate_result(x integer) UNION SELECT intermediate_result.y FROM read_intermediate_result('147_1'::text, 'binary'::citus_copy_format) intermediate_result(y integer) +DEBUG: Plan 147 query after replacing subqueries and CTEs: SELECT count(DISTINCT x) AS count FROM (SELECT intermediate_result.x FROM read_intermediate_result('147_3'::text, 'binary'::citus_copy_format) intermediate_result(x integer)) t(x) ORDER BY (count(DISTINCT x)) DEBUG: Creating router plan DEBUG: Plan is router executable count @@ -676,12 +698,12 @@ DEBUG: Plan is router executable (1 row) select count(DISTINCT t.x) FROM ((SELECT count(DISTINCT x) FROM test) UNION (SELECT count(DISTINCT y) FROM test)) as t(x) ORDER BY 1; -DEBUG: generating subplan 147_1 for subquery SELECT count(DISTINCT x) AS count FROM recursive_union.test -DEBUG: generating subplan 147_2 for subquery SELECT count(DISTINCT y) AS count FROM recursive_union.test +DEBUG: generating subplan 151_1 for subquery SELECT count(DISTINCT x) AS count FROM recursive_union.test +DEBUG: generating subplan 151_2 for subquery SELECT count(DISTINCT y) AS count FROM recursive_union.test DEBUG: Creating router plan DEBUG: Plan is router executable -DEBUG: generating subplan 147_3 for subquery SELECT intermediate_result.count FROM read_intermediate_result('147_1'::text, 'binary'::citus_copy_format) intermediate_result(count bigint) UNION SELECT intermediate_result.count FROM read_intermediate_result('147_2'::text, 'binary'::citus_copy_format) intermediate_result(count bigint) -DEBUG: Plan 147 query after replacing subqueries and CTEs: SELECT count(DISTINCT x) AS count FROM (SELECT intermediate_result.count FROM read_intermediate_result('147_3'::text, 'binary'::citus_copy_format) intermediate_result(count bigint)) t(x) ORDER BY (count(DISTINCT x)) +DEBUG: generating subplan 151_3 for subquery SELECT intermediate_result.count FROM read_intermediate_result('151_1'::text, 'binary'::citus_copy_format) intermediate_result(count bigint) UNION SELECT intermediate_result.count FROM read_intermediate_result('151_2'::text, 'binary'::citus_copy_format) intermediate_result(count bigint) +DEBUG: Plan 151 query after replacing subqueries and CTEs: SELECT count(DISTINCT x) AS count FROM (SELECT intermediate_result.count FROM read_intermediate_result('151_3'::text, 'binary'::citus_copy_format) intermediate_result(count bigint)) t(x) ORDER BY (count(DISTINCT x)) DEBUG: Creating router plan DEBUG: Plan is router executable count @@ -691,12 +713,12 @@ DEBUG: Plan is router executable -- other agg. distincts are also supported when group by includes partition key select avg(DISTINCT t.x) FROM ((SELECT avg(DISTINCT y) FROM test GROUP BY x) UNION (SELECT avg(DISTINCT y) FROM test GROUP BY x)) as t(x) ORDER BY 1; -DEBUG: generating subplan 151_1 for subquery SELECT avg(DISTINCT y) AS avg FROM recursive_union.test GROUP BY x -DEBUG: generating subplan 151_2 for subquery SELECT avg(DISTINCT y) AS avg FROM recursive_union.test GROUP BY x +DEBUG: generating subplan 155_1 for subquery SELECT avg(DISTINCT y) AS avg FROM recursive_union.test GROUP BY x +DEBUG: generating subplan 155_2 for subquery SELECT avg(DISTINCT y) AS avg FROM recursive_union.test GROUP BY x DEBUG: Creating router plan DEBUG: Plan is router executable -DEBUG: generating subplan 151_3 for subquery SELECT intermediate_result.avg FROM read_intermediate_result('151_1'::text, 'binary'::citus_copy_format) intermediate_result(avg numeric) UNION SELECT intermediate_result.avg FROM read_intermediate_result('151_2'::text, 'binary'::citus_copy_format) intermediate_result(avg numeric) -DEBUG: Plan 151 query after replacing subqueries and CTEs: SELECT avg(DISTINCT x) AS avg FROM (SELECT intermediate_result.avg FROM read_intermediate_result('151_3'::text, 'binary'::citus_copy_format) intermediate_result(avg numeric)) t(x) ORDER BY (avg(DISTINCT x)) +DEBUG: generating subplan 155_3 for subquery SELECT intermediate_result.avg FROM read_intermediate_result('155_1'::text, 'binary'::citus_copy_format) intermediate_result(avg numeric) UNION SELECT intermediate_result.avg FROM read_intermediate_result('155_2'::text, 'binary'::citus_copy_format) intermediate_result(avg numeric) +DEBUG: Plan 155 query after replacing subqueries and CTEs: SELECT avg(DISTINCT x) AS avg FROM (SELECT intermediate_result.avg FROM read_intermediate_result('155_3'::text, 'binary'::citus_copy_format) intermediate_result(avg numeric)) t(x) ORDER BY (avg(DISTINCT x)) DEBUG: Creating router plan DEBUG: Plan is router executable avg @@ -743,9 +765,9 @@ DEBUG: pruning merge fetch taskId 11 DETAIL: Creating dependency on merge taskId 24 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 157_1 for subquery SELECT t1.x FROM recursive_union.test t1, recursive_union.test t2 WHERE (t1.x = t2.y) LIMIT 0 -DEBUG: generating subplan 157_2 for subquery SELECT x FROM recursive_union.test -DEBUG: Plan 157 query after replacing subqueries and CTEs: SELECT intermediate_result.x FROM read_intermediate_result('157_2'::text, 'binary'::citus_copy_format) intermediate_result(x integer) INTERSECT SELECT intermediate_result.x FROM read_intermediate_result('157_1'::text, 'binary'::citus_copy_format) intermediate_result(x integer) ORDER BY 1 DESC +DEBUG: generating subplan 161_1 for subquery SELECT t1.x FROM recursive_union.test t1, recursive_union.test t2 WHERE (t1.x = t2.y) LIMIT 0 +DEBUG: generating subplan 161_2 for subquery SELECT x FROM recursive_union.test +DEBUG: Plan 161 query after replacing subqueries and CTEs: SELECT intermediate_result.x FROM read_intermediate_result('161_2'::text, 'binary'::citus_copy_format) intermediate_result(x integer) INTERSECT SELECT intermediate_result.x FROM read_intermediate_result('161_1'::text, 'binary'::citus_copy_format) intermediate_result(x integer) ORDER BY 1 DESC DEBUG: Creating router plan DEBUG: Plan is router executable x @@ -754,7 +776,7 @@ DEBUG: Plan is router executable -- repartition is recursively planned with the set operation (SELECT x FROM test) INTERSECT (SELECT t1.x FROM test as t1, test as t2 WHERE t1.x = t2.y) ORDER BY 1 DESC; -DEBUG: generating subplan 160_1 for subquery SELECT x FROM recursive_union.test +DEBUG: generating subplan 164_1 for subquery SELECT x FROM recursive_union.test DEBUG: join prunable for task partitionId 0 and 1 DEBUG: join prunable for task partitionId 0 and 2 DEBUG: join prunable for task partitionId 0 and 3 @@ -785,8 +807,8 @@ DEBUG: pruning merge fetch taskId 11 DETAIL: Creating dependency on merge taskId 24 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 160_2 for subquery SELECT t1.x FROM recursive_union.test t1, recursive_union.test t2 WHERE (t1.x = t2.y) -DEBUG: Plan 160 query after replacing subqueries and CTEs: SELECT intermediate_result.x FROM read_intermediate_result('160_1'::text, 'binary'::citus_copy_format) intermediate_result(x integer) INTERSECT SELECT intermediate_result.x FROM read_intermediate_result('160_2'::text, 'binary'::citus_copy_format) intermediate_result(x integer) ORDER BY 1 DESC +DEBUG: generating subplan 164_2 for subquery SELECT t1.x FROM recursive_union.test t1, recursive_union.test t2 WHERE (t1.x = t2.y) +DEBUG: Plan 164 query after replacing subqueries and CTEs: SELECT intermediate_result.x FROM read_intermediate_result('164_1'::text, 'binary'::citus_copy_format) intermediate_result(x integer) INTERSECT SELECT intermediate_result.x FROM read_intermediate_result('164_2'::text, 'binary'::citus_copy_format) intermediate_result(x integer) ORDER BY 1 DESC DEBUG: Creating router plan DEBUG: Plan is router executable x @@ -799,12 +821,12 @@ SET citus.enable_repartition_joins TO OFF; -- this should be recursively planned CREATE VIEW set_view_recursive AS (SELECT y FROM test) UNION (SELECT y FROM test); SELECT * FROM set_view_recursive ORDER BY 1 DESC; -DEBUG: generating subplan 163_1 for subquery SELECT y FROM recursive_union.test -DEBUG: generating subplan 163_2 for subquery SELECT y FROM recursive_union.test +DEBUG: generating subplan 167_1 for subquery SELECT y FROM recursive_union.test +DEBUG: generating subplan 167_2 for subquery SELECT y FROM recursive_union.test DEBUG: Creating router plan DEBUG: Plan is router executable -DEBUG: generating subplan 163_3 for subquery SELECT intermediate_result.y FROM read_intermediate_result('163_1'::text, 'binary'::citus_copy_format) intermediate_result(y integer) UNION SELECT intermediate_result.y FROM read_intermediate_result('163_2'::text, 'binary'::citus_copy_format) intermediate_result(y integer) -DEBUG: Plan 163 query after replacing subqueries and CTEs: SELECT y FROM (SELECT intermediate_result.y FROM read_intermediate_result('163_3'::text, 'binary'::citus_copy_format) intermediate_result(y integer)) set_view_recursive ORDER BY y DESC +DEBUG: generating subplan 167_3 for subquery SELECT intermediate_result.y FROM read_intermediate_result('167_1'::text, 'binary'::citus_copy_format) intermediate_result(y integer) UNION SELECT intermediate_result.y FROM read_intermediate_result('167_2'::text, 'binary'::citus_copy_format) intermediate_result(y integer) +DEBUG: Plan 167 query after replacing subqueries and CTEs: SELECT y FROM (SELECT intermediate_result.y FROM read_intermediate_result('167_3'::text, 'binary'::citus_copy_format) intermediate_result(y integer)) set_view_recursive ORDER BY y DESC DEBUG: Creating router plan DEBUG: Plan is router executable y @@ -825,12 +847,12 @@ SELECT * FROM set_view_pushdown ORDER BY 1 DESC; -- this should be recursively planned CREATE VIEW set_view_recursive_second AS SELECT u.x, test.y FROM ((SELECT x, y FROM test) UNION (SELECT 1, 1 FROM test)) u JOIN test USING (x) ORDER BY 1,2; SELECT * FROM set_view_recursive_second; -DEBUG: generating subplan 168_1 for subquery SELECT x, y FROM recursive_union.test -DEBUG: generating subplan 168_2 for subquery SELECT 1, 1 FROM recursive_union.test +DEBUG: generating subplan 172_1 for subquery SELECT x, y FROM recursive_union.test +DEBUG: generating subplan 172_2 for subquery SELECT 1, 1 FROM recursive_union.test DEBUG: Creating router plan DEBUG: Plan is router executable -DEBUG: generating subplan 168_3 for subquery SELECT intermediate_result.x, intermediate_result.y FROM read_intermediate_result('168_1'::text, 'binary'::citus_copy_format) intermediate_result(x integer, y integer) UNION SELECT intermediate_result."?column?", intermediate_result."?column?_1" AS "?column?" FROM read_intermediate_result('168_2'::text, 'binary'::citus_copy_format) intermediate_result("?column?" integer, "?column?_1" integer) -DEBUG: Plan 168 query after replacing subqueries and CTEs: SELECT x, y FROM (SELECT u.x, test.y FROM ((SELECT intermediate_result.x, intermediate_result.y FROM read_intermediate_result('168_3'::text, 'binary'::citus_copy_format) intermediate_result(x integer, y integer)) u JOIN recursive_union.test USING (x)) ORDER BY u.x, test.y) set_view_recursive_second +DEBUG: generating subplan 172_3 for subquery SELECT intermediate_result.x, intermediate_result.y FROM read_intermediate_result('172_1'::text, 'binary'::citus_copy_format) intermediate_result(x integer, y integer) UNION SELECT intermediate_result."?column?", intermediate_result."?column?_1" AS "?column?" FROM read_intermediate_result('172_2'::text, 'binary'::citus_copy_format) intermediate_result("?column?" integer, "?column?_1" integer) +DEBUG: Plan 172 query after replacing subqueries and CTEs: SELECT x, y FROM (SELECT u.x, test.y FROM ((SELECT intermediate_result.x, intermediate_result.y FROM read_intermediate_result('172_3'::text, 'binary'::citus_copy_format) intermediate_result(x integer, y integer)) u JOIN recursive_union.test USING (x)) ORDER BY u.x, test.y) set_view_recursive_second x | y ---+--- 1 | 1 @@ -839,19 +861,19 @@ DEBUG: Plan 168 query after replacing subqueries and CTEs: SELECT x, y FROM (SE -- this should create lots of recursive calls since both views and set operations lead to recursive plans :) ((SELECT x FROM set_view_recursive_second) INTERSECT (SELECT * FROM set_view_recursive)) EXCEPT (SELECT * FROM set_view_pushdown); -DEBUG: generating subplan 172_1 for subquery SELECT x, y FROM recursive_union.test -DEBUG: generating subplan 172_2 for subquery SELECT 1, 1 FROM recursive_union.test +DEBUG: generating subplan 176_1 for subquery SELECT x, y FROM recursive_union.test +DEBUG: generating subplan 176_2 for subquery SELECT 1, 1 FROM recursive_union.test DEBUG: Creating router plan DEBUG: Plan is router executable -DEBUG: generating subplan 172_3 for subquery SELECT intermediate_result.x, intermediate_result.y FROM read_intermediate_result('172_1'::text, 'binary'::citus_copy_format) intermediate_result(x integer, y integer) UNION SELECT intermediate_result."?column?", intermediate_result."?column?_1" AS "?column?" FROM read_intermediate_result('172_2'::text, 'binary'::citus_copy_format) intermediate_result("?column?" integer, "?column?_1" integer) -DEBUG: generating subplan 172_4 for subquery SELECT y FROM recursive_union.test -DEBUG: generating subplan 172_5 for subquery SELECT y FROM recursive_union.test +DEBUG: generating subplan 176_3 for subquery SELECT intermediate_result.x, intermediate_result.y FROM read_intermediate_result('176_1'::text, 'binary'::citus_copy_format) intermediate_result(x integer, y integer) UNION SELECT intermediate_result."?column?", intermediate_result."?column?_1" AS "?column?" FROM read_intermediate_result('176_2'::text, 'binary'::citus_copy_format) intermediate_result("?column?" integer, "?column?_1" integer) +DEBUG: generating subplan 176_4 for subquery SELECT y FROM recursive_union.test +DEBUG: generating subplan 176_5 for subquery SELECT y FROM recursive_union.test DEBUG: Creating router plan DEBUG: Plan is router executable -DEBUG: generating subplan 172_6 for subquery SELECT intermediate_result.y FROM read_intermediate_result('172_4'::text, 'binary'::citus_copy_format) intermediate_result(y integer) UNION SELECT intermediate_result.y FROM read_intermediate_result('172_5'::text, 'binary'::citus_copy_format) intermediate_result(y integer) -DEBUG: generating subplan 172_7 for subquery SELECT x FROM (SELECT u.x, test.y FROM ((SELECT intermediate_result.x, intermediate_result.y FROM read_intermediate_result('172_3'::text, 'binary'::citus_copy_format) intermediate_result(x integer, y integer)) u JOIN recursive_union.test USING (x)) ORDER BY u.x, test.y) set_view_recursive_second -DEBUG: generating subplan 172_8 for subquery SELECT x FROM (SELECT test.x FROM recursive_union.test UNION SELECT test.x FROM recursive_union.test) set_view_pushdown -DEBUG: Plan 172 query after replacing subqueries and CTEs: (SELECT intermediate_result.x FROM read_intermediate_result('172_7'::text, 'binary'::citus_copy_format) intermediate_result(x integer) INTERSECT SELECT set_view_recursive.y FROM (SELECT intermediate_result.y FROM read_intermediate_result('172_6'::text, 'binary'::citus_copy_format) intermediate_result(y integer)) set_view_recursive) EXCEPT SELECT intermediate_result.x FROM read_intermediate_result('172_8'::text, 'binary'::citus_copy_format) intermediate_result(x integer) +DEBUG: generating subplan 176_6 for subquery SELECT intermediate_result.y FROM read_intermediate_result('176_4'::text, 'binary'::citus_copy_format) intermediate_result(y integer) UNION SELECT intermediate_result.y FROM read_intermediate_result('176_5'::text, 'binary'::citus_copy_format) intermediate_result(y integer) +DEBUG: generating subplan 176_7 for subquery SELECT x FROM (SELECT u.x, test.y FROM ((SELECT intermediate_result.x, intermediate_result.y FROM read_intermediate_result('176_3'::text, 'binary'::citus_copy_format) intermediate_result(x integer, y integer)) u JOIN recursive_union.test USING (x)) ORDER BY u.x, test.y) set_view_recursive_second +DEBUG: generating subplan 176_8 for subquery SELECT x FROM (SELECT test.x FROM recursive_union.test UNION SELECT test.x FROM recursive_union.test) set_view_pushdown +DEBUG: Plan 176 query after replacing subqueries and CTEs: (SELECT intermediate_result.x FROM read_intermediate_result('176_7'::text, 'binary'::citus_copy_format) intermediate_result(x integer) INTERSECT SELECT set_view_recursive.y FROM (SELECT intermediate_result.y FROM read_intermediate_result('176_6'::text, 'binary'::citus_copy_format) intermediate_result(y integer)) set_view_recursive) EXCEPT SELECT intermediate_result.x FROM read_intermediate_result('176_8'::text, 'binary'::citus_copy_format) intermediate_result(x integer) DEBUG: Creating router plan DEBUG: Plan is router executable x diff --git a/src/test/regress/expected/subqueries_not_supported.out b/src/test/regress/expected/subqueries_not_supported.out index 1dd59b325..cea279dd7 100644 --- a/src/test/regress/expected/subqueries_not_supported.out +++ b/src/test/regress/expected/subqueries_not_supported.out @@ -60,24 +60,6 @@ FROM LIMIT 5 ) as foo; ERROR: array_agg with order by is unsupported --- we don't support queries with recurring tuples in the FROM --- clause and subquery in WHERE clause -SELECT - * -FROM - ( - SELECT - users_table.user_id - FROM - users_table, (SELECT user_id FROM events_table) as evs - WHERE users_table.user_id = evs.user_id - LIMIT 5 - ) as foo WHERE user_id IN (SELECT count(*) FROM users_table GROUP BY user_id); -DEBUG: push down of limit count: 5 -DEBUG: generating subplan 10_1 for subquery SELECT users_table.user_id FROM public.users_table, (SELECT events_table.user_id FROM public.events_table) evs WHERE (users_table.user_id = evs.user_id) LIMIT 5 -DEBUG: Plan 10 query after replacing subqueries and CTEs: SELECT user_id FROM (SELECT intermediate_result.user_id FROM read_intermediate_result('10_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) foo WHERE (user_id IN (SELECT count(*) AS count FROM public.users_table GROUP BY users_table.user_id)) -ERROR: cannot pushdown the subquery -DETAIL: Complex subqueries and CTEs are not allowed in the FROM clause when the query has subqueries in the WHERE clause -- we don't support recursive subqueries when router executor is disabled SET citus.enable_router_execution TO false; SELECT @@ -94,8 +76,8 @@ FROM ) as foo ORDER BY 1 DESC; DEBUG: push down of limit count: 5 -DEBUG: generating subplan 12_1 for subquery SELECT DISTINCT users_table.user_id FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.user_id) AND (events_table.event_type = ANY (ARRAY[1, 2, 3, 4]))) ORDER BY users_table.user_id DESC LIMIT 5 -DEBUG: Plan 12 query after replacing subqueries and CTEs: SELECT user_id FROM (SELECT intermediate_result.user_id FROM read_intermediate_result('12_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) foo ORDER BY user_id DESC +DEBUG: generating subplan 10_1 for subquery SELECT DISTINCT users_table.user_id FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.user_id) AND (events_table.event_type = ANY (ARRAY[1, 2, 3, 4]))) ORDER BY users_table.user_id DESC LIMIT 5 +DEBUG: Plan 10 query after replacing subqueries and CTEs: SELECT user_id FROM (SELECT intermediate_result.user_id FROM read_intermediate_result('10_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) foo ORDER BY user_id DESC ERROR: cannot handle complex subqueries when the router executor is disabled SET citus.enable_router_execution TO true; -- window functions are not allowed if they're not partitioned on the distribution column @@ -139,8 +121,8 @@ FROM (SELECT users_table.value_2 FROM users_table, events_table WHERE users_table.user_id = events_table.user_id AND event_type IN (5,6,7,8)) as bar ON(foo.value_2 = bar.value_2); DEBUG: push down of limit count: 5 -DEBUG: generating subplan 17_1 for subquery SELECT users_table.value_2 FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.user_id) AND (events_table.event_type = ANY (ARRAY[1, 2, 3, 4]))) LIMIT 5 -DEBUG: Plan 17 query after replacing subqueries and CTEs: SELECT foo.value_2 FROM ((SELECT intermediate_result.value_2 FROM read_intermediate_result('17_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 = events_table.user_id) AND (events_table.event_type = ANY (ARRAY[5, 6, 7, 8])))) bar ON ((foo.value_2 = bar.value_2))) +DEBUG: generating subplan 15_1 for subquery SELECT users_table.value_2 FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.user_id) AND (events_table.event_type = ANY (ARRAY[1, 2, 3, 4]))) LIMIT 5 +DEBUG: Plan 15 query after replacing subqueries and CTEs: SELECT foo.value_2 FROM ((SELECT intermediate_result.value_2 FROM read_intermediate_result('15_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 = events_table.user_id) AND (events_table.event_type = ANY (ARRAY[5, 6, 7, 8])))) bar ON ((foo.value_2 = 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_and_cte.out b/src/test/regress/expected/subquery_and_cte.out index e2c63a7a2..4f62df4a9 100644 --- a/src/test/regress/expected/subquery_and_cte.out +++ b/src/test/regress/expected/subquery_and_cte.out @@ -113,10 +113,8 @@ DEBUG: Plan 10 query after replacing subqueries and CTEs: SELECT DISTINCT cte.u 1 (4 rows) --- a very similar query as the above, but this time errors --- out since we don't support subqueries in WHERE clause --- when there is only intermediate results on the range table --- note that this time subquery in WHERE clause is not replaced +-- subquery in WHERE clause is planned recursively due to the recurring table +-- in FROM clause WITH cte AS ( WITH local_cte AS ( SELECT * FROM users_table_local @@ -135,9 +133,18 @@ DEBUG: generating subplan 14_1 for CTE cte: WITH local_cte AS (SELECT users_tab DEBUG: generating subplan 15_1 for CTE local_cte: SELECT user_id, "time", value_1, value_2, value_3, value_4 FROM subquery_and_ctes.users_table_local DEBUG: generating subplan 15_2 for CTE dist_cte: SELECT user_id FROM public.events_table DEBUG: Plan 15 query after replacing subqueries and CTEs: SELECT dist_cte.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('15_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)) local_cte JOIN (SELECT intermediate_result.user_id FROM read_intermediate_result('15_2'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) dist_cte ON ((dist_cte.user_id = local_cte.user_id))) -DEBUG: Plan 14 query after replacing subqueries and CTEs: SELECT DISTINCT user_id FROM (SELECT intermediate_result.user_id FROM read_intermediate_result('14_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) cte WHERE (user_id IN (SELECT DISTINCT users_table.user_id FROM public.users_table WHERE ((users_table.value_1 >= 1) AND (users_table.value_1 <= 20)))) ORDER BY user_id DESC -ERROR: cannot pushdown the subquery -DETAIL: Complex subqueries and CTEs are not allowed in the FROM clause when the query has subqueries in the WHERE clause +DEBUG: generating subplan 14_2 for subquery SELECT DISTINCT user_id FROM public.users_table WHERE ((value_1 >= 1) AND (value_1 <= 20)) +DEBUG: Plan 14 query after replacing subqueries and CTEs: SELECT DISTINCT user_id FROM (SELECT intermediate_result.user_id FROM read_intermediate_result('14_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) cte WHERE (user_id IN (SELECT intermediate_result.user_id FROM read_intermediate_result('14_2'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer))) ORDER BY user_id DESC + user_id +--------- + 6 + 5 + 4 + 3 + 2 + 1 +(6 rows) + -- CTEs inside a subquery and the final query becomes a router -- query SELECT @@ -154,8 +161,8 @@ FROM event_type IN (1,2,3,4) ) SELECT * FROM cte ORDER BY 1 DESC ) as foo; -DEBUG: generating subplan 17_1 for CTE cte: SELECT DISTINCT users_table.user_id FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.user_id) AND (events_table.event_type = ANY (ARRAY[1, 2, 3, 4]))) -DEBUG: Plan 17 query after replacing subqueries and CTEs: SELECT user_id FROM (SELECT cte.user_id FROM (SELECT intermediate_result.user_id FROM read_intermediate_result('17_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) cte ORDER BY cte.user_id DESC) foo +DEBUG: generating subplan 18_1 for CTE cte: SELECT DISTINCT users_table.user_id FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.user_id) AND (events_table.event_type = ANY (ARRAY[1, 2, 3, 4]))) +DEBUG: Plan 18 query after replacing subqueries and CTEs: SELECT user_id FROM (SELECT cte.user_id FROM (SELECT intermediate_result.user_id FROM read_intermediate_result('18_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) cte ORDER BY cte.user_id DESC) foo user_id --------- 6 @@ -193,8 +200,8 @@ FROM ) as bar WHERE foo.user_id = bar.user_id; -DEBUG: generating subplan 19_1 for CTE cte: SELECT DISTINCT users_table.user_id FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.user_id) AND (events_table.event_type = ANY (ARRAY[1, 2, 3, 4]))) -DEBUG: Plan 19 query after replacing subqueries and CTEs: SELECT bar.user_id FROM (SELECT cte.user_id FROM (SELECT intermediate_result.user_id FROM read_intermediate_result('19_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) cte ORDER BY cte.user_id DESC) foo, (SELECT DISTINCT users_table.user_id FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.user_id) AND (events_table.event_type = ANY (ARRAY[1, 2, 3, 4])))) bar WHERE (foo.user_id = bar.user_id) +DEBUG: generating subplan 20_1 for CTE cte: SELECT DISTINCT users_table.user_id FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.user_id) AND (events_table.event_type = ANY (ARRAY[1, 2, 3, 4]))) +DEBUG: Plan 20 query after replacing subqueries and CTEs: SELECT bar.user_id FROM (SELECT cte.user_id FROM (SELECT intermediate_result.user_id FROM read_intermediate_result('20_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) cte ORDER BY cte.user_id DESC) foo, (SELECT DISTINCT users_table.user_id FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.user_id) AND (events_table.event_type = ANY (ARRAY[1, 2, 3, 4])))) bar WHERE (foo.user_id = bar.user_id) user_id --------- 5 @@ -246,11 +253,11 @@ FROM ) as bar WHERE foo.user_id = bar.user_id ORDER BY 1 DESC LIMIT 5; -DEBUG: generating subplan 21_1 for CTE cte: SELECT DISTINCT users_table.user_id FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.user_id) AND (events_table.event_type = ANY (ARRAY[1, 2, 3, 4]))) -DEBUG: generating subplan 21_2 for CTE cte: SELECT events_table.event_type, users_table.user_id FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.user_id) AND (users_table.value_1 = ANY (ARRAY[1, 2]))) +DEBUG: generating subplan 22_1 for CTE cte: SELECT DISTINCT users_table.user_id FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.user_id) AND (events_table.event_type = ANY (ARRAY[1, 2, 3, 4]))) +DEBUG: generating subplan 22_2 for CTE cte: SELECT events_table.event_type, users_table.user_id FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.user_id) AND (users_table.value_1 = ANY (ARRAY[1, 2]))) DEBUG: push down of limit count: 2 -DEBUG: generating subplan 21_3 for subquery SELECT users_table.user_id, some_events.event_type FROM public.users_table, (SELECT cte.event_type, cte.user_id FROM (SELECT intermediate_result.event_type, intermediate_result.user_id FROM read_intermediate_result('21_2'::text, 'binary'::citus_copy_format) intermediate_result(event_type integer, user_id integer)) cte ORDER BY cte.event_type DESC) some_events WHERE ((users_table.user_id = some_events.user_id) AND (some_events.event_type = ANY (ARRAY[1, 2, 3, 4]))) ORDER BY some_events.event_type, users_table.user_id LIMIT 2 -DEBUG: Plan 21 query after replacing subqueries and CTEs: SELECT DISTINCT bar.user_id FROM (SELECT cte.user_id FROM (SELECT intermediate_result.user_id FROM read_intermediate_result('21_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) cte ORDER BY cte.user_id DESC) foo, (SELECT intermediate_result.user_id, intermediate_result.event_type FROM read_intermediate_result('21_3'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer, event_type integer)) bar WHERE (foo.user_id = bar.user_id) ORDER BY bar.user_id DESC LIMIT 5 +DEBUG: generating subplan 22_3 for subquery SELECT users_table.user_id, some_events.event_type FROM public.users_table, (SELECT cte.event_type, cte.user_id FROM (SELECT intermediate_result.event_type, intermediate_result.user_id FROM read_intermediate_result('22_2'::text, 'binary'::citus_copy_format) intermediate_result(event_type integer, user_id integer)) cte ORDER BY cte.event_type DESC) some_events WHERE ((users_table.user_id = some_events.user_id) AND (some_events.event_type = ANY (ARRAY[1, 2, 3, 4]))) ORDER BY some_events.event_type, users_table.user_id LIMIT 2 +DEBUG: Plan 22 query after replacing subqueries and CTEs: SELECT DISTINCT bar.user_id FROM (SELECT cte.user_id FROM (SELECT intermediate_result.user_id FROM read_intermediate_result('22_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) cte ORDER BY cte.user_id DESC) foo, (SELECT intermediate_result.user_id, intermediate_result.event_type FROM read_intermediate_result('22_3'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer, event_type integer)) bar WHERE (foo.user_id = bar.user_id) ORDER BY bar.user_id DESC LIMIT 5 user_id --------- 1 @@ -283,14 +290,14 @@ SELECT * FROM foo.user_id = events_table.value_2 ORDER BY 3 DESC, 2 DESC, 1 DESC LIMIT 5; -DEBUG: generating subplan 25_1 for CTE cte: WITH local_cte AS (SELECT users_table_local.user_id, users_table_local."time", users_table_local.value_1, users_table_local.value_2, users_table_local.value_3, users_table_local.value_4 FROM subquery_and_ctes.users_table_local), dist_cte AS (SELECT events_table.user_id FROM public.events_table) SELECT dist_cte.user_id FROM (local_cte JOIN dist_cte ON ((dist_cte.user_id = local_cte.user_id))) -DEBUG: generating subplan 26_1 for CTE local_cte: SELECT user_id, "time", value_1, value_2, value_3, value_4 FROM subquery_and_ctes.users_table_local -DEBUG: generating subplan 26_2 for CTE dist_cte: SELECT user_id FROM public.events_table -DEBUG: Plan 26 query after replacing subqueries and CTEs: SELECT dist_cte.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('26_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)) local_cte JOIN (SELECT intermediate_result.user_id FROM read_intermediate_result('26_2'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) dist_cte ON ((dist_cte.user_id = local_cte.user_id))) -DEBUG: generating subplan 25_2 for CTE cte_in_where: SELECT DISTINCT value_2 FROM public.users_table WHERE ((value_1 >= 1) AND (value_1 <= 20)) ORDER BY value_2 LIMIT 5 +DEBUG: generating subplan 26_1 for CTE cte: WITH local_cte AS (SELECT users_table_local.user_id, users_table_local."time", users_table_local.value_1, users_table_local.value_2, users_table_local.value_3, users_table_local.value_4 FROM subquery_and_ctes.users_table_local), dist_cte AS (SELECT events_table.user_id FROM public.events_table) SELECT dist_cte.user_id FROM (local_cte JOIN dist_cte ON ((dist_cte.user_id = local_cte.user_id))) +DEBUG: generating subplan 27_1 for CTE local_cte: SELECT user_id, "time", value_1, value_2, value_3, value_4 FROM subquery_and_ctes.users_table_local +DEBUG: generating subplan 27_2 for CTE dist_cte: SELECT user_id FROM public.events_table +DEBUG: Plan 27 query after replacing subqueries and CTEs: SELECT dist_cte.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('27_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)) local_cte JOIN (SELECT intermediate_result.user_id FROM read_intermediate_result('27_2'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) dist_cte ON ((dist_cte.user_id = local_cte.user_id))) +DEBUG: generating subplan 26_2 for CTE cte_in_where: SELECT DISTINCT value_2 FROM public.users_table WHERE ((value_1 >= 1) AND (value_1 <= 20)) ORDER BY value_2 LIMIT 5 DEBUG: push down of limit count: 5 -DEBUG: generating subplan 25_3 for subquery SELECT DISTINCT cte.user_id FROM public.users_table, (SELECT intermediate_result.user_id FROM read_intermediate_result('25_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) cte WHERE ((users_table.user_id = cte.user_id) AND (users_table.user_id IN (SELECT cte_in_where.value_2 FROM (SELECT intermediate_result.value_2 FROM read_intermediate_result('25_2'::text, 'binary'::citus_copy_format) intermediate_result(value_2 integer)) cte_in_where))) ORDER BY cte.user_id DESC -DEBUG: Plan 25 query after replacing subqueries and CTEs: SELECT foo.user_id, events_table.user_id, events_table."time", events_table.event_type, events_table.value_2, events_table.value_3, events_table.value_4 FROM (SELECT intermediate_result.user_id FROM read_intermediate_result('25_3'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) foo, public.events_table WHERE (foo.user_id = events_table.value_2) ORDER BY events_table."time" DESC, events_table.user_id DESC, foo.user_id DESC LIMIT 5 +DEBUG: generating subplan 26_3 for subquery SELECT DISTINCT cte.user_id FROM public.users_table, (SELECT intermediate_result.user_id FROM read_intermediate_result('26_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) cte WHERE ((users_table.user_id = cte.user_id) AND (users_table.user_id IN (SELECT cte_in_where.value_2 FROM (SELECT intermediate_result.value_2 FROM read_intermediate_result('26_2'::text, 'binary'::citus_copy_format) intermediate_result(value_2 integer)) cte_in_where))) ORDER BY cte.user_id DESC +DEBUG: Plan 26 query after replacing subqueries and CTEs: SELECT foo.user_id, events_table.user_id, events_table."time", events_table.event_type, events_table.value_2, events_table.value_3, events_table.value_4 FROM (SELECT intermediate_result.user_id FROM read_intermediate_result('26_3'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) foo, public.events_table WHERE (foo.user_id = events_table.value_2) ORDER BY events_table."time" DESC, events_table.user_id DESC, foo.user_id DESC LIMIT 5 DEBUG: push down of limit count: 5 user_id | user_id | time | event_type | value_2 | value_3 | value_4 ---------+---------+---------------------------------+------------+---------+---------+--------- @@ -332,17 +339,17 @@ FROM ORDER BY 1 DESC LIMIT 5 ) as foo WHERE foo.user_id = cte.user_id; -DEBUG: generating subplan 30_1 for CTE cte: WITH local_cte AS (SELECT users_table_local.user_id, users_table_local."time", users_table_local.value_1, users_table_local.value_2, users_table_local.value_3, users_table_local.value_4 FROM subquery_and_ctes.users_table_local), dist_cte AS (SELECT events_table.user_id FROM public.events_table, (SELECT DISTINCT users_table.value_2 FROM public.users_table OFFSET 0) foo WHERE ((events_table.user_id = foo.value_2) AND (events_table.user_id IN (SELECT DISTINCT users_table.value_1 FROM public.users_table ORDER BY users_table.value_1 LIMIT 3)))) SELECT dist_cte.user_id FROM (local_cte JOIN dist_cte ON ((dist_cte.user_id = local_cte.user_id))) -DEBUG: generating subplan 31_1 for CTE local_cte: SELECT user_id, "time", value_1, value_2, value_3, value_4 FROM subquery_and_ctes.users_table_local -DEBUG: generating subplan 31_2 for CTE dist_cte: SELECT events_table.user_id FROM public.events_table, (SELECT DISTINCT users_table.value_2 FROM public.users_table OFFSET 0) foo WHERE ((events_table.user_id = foo.value_2) AND (events_table.user_id IN (SELECT DISTINCT users_table.value_1 FROM public.users_table ORDER BY users_table.value_1 LIMIT 3))) +DEBUG: generating subplan 31_1 for CTE cte: WITH local_cte AS (SELECT users_table_local.user_id, users_table_local."time", users_table_local.value_1, users_table_local.value_2, users_table_local.value_3, users_table_local.value_4 FROM subquery_and_ctes.users_table_local), dist_cte AS (SELECT events_table.user_id FROM public.events_table, (SELECT DISTINCT users_table.value_2 FROM public.users_table OFFSET 0) foo WHERE ((events_table.user_id = foo.value_2) AND (events_table.user_id IN (SELECT DISTINCT users_table.value_1 FROM public.users_table ORDER BY users_table.value_1 LIMIT 3)))) SELECT dist_cte.user_id FROM (local_cte JOIN dist_cte ON ((dist_cte.user_id = local_cte.user_id))) +DEBUG: generating subplan 32_1 for CTE local_cte: SELECT user_id, "time", value_1, value_2, value_3, value_4 FROM subquery_and_ctes.users_table_local +DEBUG: generating subplan 32_2 for CTE dist_cte: SELECT events_table.user_id FROM public.events_table, (SELECT DISTINCT users_table.value_2 FROM public.users_table OFFSET 0) foo WHERE ((events_table.user_id = foo.value_2) AND (events_table.user_id IN (SELECT DISTINCT users_table.value_1 FROM public.users_table ORDER BY users_table.value_1 LIMIT 3))) DEBUG: push down of limit count: 3 -DEBUG: generating subplan 32_1 for subquery SELECT DISTINCT value_1 FROM public.users_table ORDER BY value_1 LIMIT 3 -DEBUG: generating subplan 32_2 for subquery SELECT DISTINCT value_2 FROM public.users_table OFFSET 0 -DEBUG: Plan 32 query after replacing subqueries and CTEs: SELECT events_table.user_id FROM public.events_table, (SELECT intermediate_result.value_2 FROM read_intermediate_result('32_2'::text, 'binary'::citus_copy_format) intermediate_result(value_2 integer)) foo WHERE ((events_table.user_id = foo.value_2) AND (events_table.user_id IN (SELECT intermediate_result.value_1 FROM read_intermediate_result('32_1'::text, 'binary'::citus_copy_format) intermediate_result(value_1 integer)))) -DEBUG: Plan 31 query after replacing subqueries and CTEs: SELECT dist_cte.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('31_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)) local_cte JOIN (SELECT intermediate_result.user_id FROM read_intermediate_result('31_2'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) dist_cte ON ((dist_cte.user_id = local_cte.user_id))) +DEBUG: generating subplan 33_1 for subquery SELECT DISTINCT value_1 FROM public.users_table ORDER BY value_1 LIMIT 3 +DEBUG: generating subplan 33_2 for subquery SELECT DISTINCT value_2 FROM public.users_table OFFSET 0 +DEBUG: Plan 33 query after replacing subqueries and CTEs: SELECT events_table.user_id FROM public.events_table, (SELECT intermediate_result.value_2 FROM read_intermediate_result('33_2'::text, 'binary'::citus_copy_format) intermediate_result(value_2 integer)) foo WHERE ((events_table.user_id = foo.value_2) AND (events_table.user_id IN (SELECT intermediate_result.value_1 FROM read_intermediate_result('33_1'::text, 'binary'::citus_copy_format) intermediate_result(value_1 integer)))) +DEBUG: Plan 32 query after replacing subqueries and CTEs: SELECT dist_cte.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('32_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)) local_cte JOIN (SELECT intermediate_result.user_id FROM read_intermediate_result('32_2'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) dist_cte ON ((dist_cte.user_id = local_cte.user_id))) DEBUG: push down of limit count: 5 -DEBUG: generating subplan 30_2 for subquery SELECT DISTINCT users_table.user_id FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.user_id) AND (events_table.event_type = ANY (ARRAY[1, 2, 3, 4]))) ORDER BY users_table.user_id DESC LIMIT 5 -DEBUG: Plan 30 query after replacing subqueries and CTEs: SELECT count(*) AS count FROM (SELECT intermediate_result.user_id FROM read_intermediate_result('30_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) cte, (SELECT intermediate_result.user_id FROM read_intermediate_result('30_2'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) foo WHERE (foo.user_id = cte.user_id) +DEBUG: generating subplan 31_2 for subquery SELECT DISTINCT users_table.user_id FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.user_id) AND (events_table.event_type = ANY (ARRAY[1, 2, 3, 4]))) ORDER BY users_table.user_id DESC LIMIT 5 +DEBUG: Plan 31 query after replacing subqueries and CTEs: SELECT count(*) AS count FROM (SELECT intermediate_result.user_id FROM read_intermediate_result('31_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) cte, (SELECT intermediate_result.user_id FROM read_intermediate_result('31_2'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) foo WHERE (foo.user_id = cte.user_id) count ------- 432 @@ -386,18 +393,18 @@ FROM ) as foo, users_table WHERE foo.cnt > users_table.value_2 ORDER BY 3 DESC, 1 DESC, 2 DESC, 4 DESC LIMIT 5; -DEBUG: generating subplan 36_1 for CTE cte: WITH local_cte AS (SELECT users_table_local.user_id, users_table_local."time", users_table_local.value_1, users_table_local.value_2, users_table_local.value_3, users_table_local.value_4 FROM subquery_and_ctes.users_table_local), dist_cte AS (SELECT events_table.user_id FROM public.events_table, (SELECT DISTINCT users_table.value_2 FROM public.users_table OFFSET 0) foo WHERE ((events_table.user_id = foo.value_2) AND (events_table.user_id IN (SELECT DISTINCT users_table.value_1 FROM public.users_table ORDER BY users_table.value_1 LIMIT 3)))) SELECT dist_cte.user_id FROM (local_cte JOIN dist_cte ON ((dist_cte.user_id = local_cte.user_id))) -DEBUG: generating subplan 37_1 for CTE local_cte: SELECT user_id, "time", value_1, value_2, value_3, value_4 FROM subquery_and_ctes.users_table_local -DEBUG: generating subplan 37_2 for CTE dist_cte: SELECT events_table.user_id FROM public.events_table, (SELECT DISTINCT users_table.value_2 FROM public.users_table OFFSET 0) foo WHERE ((events_table.user_id = foo.value_2) AND (events_table.user_id IN (SELECT DISTINCT users_table.value_1 FROM public.users_table ORDER BY users_table.value_1 LIMIT 3))) +DEBUG: generating subplan 37_1 for CTE cte: WITH local_cte AS (SELECT users_table_local.user_id, users_table_local."time", users_table_local.value_1, users_table_local.value_2, users_table_local.value_3, users_table_local.value_4 FROM subquery_and_ctes.users_table_local), dist_cte AS (SELECT events_table.user_id FROM public.events_table, (SELECT DISTINCT users_table.value_2 FROM public.users_table OFFSET 0) foo WHERE ((events_table.user_id = foo.value_2) AND (events_table.user_id IN (SELECT DISTINCT users_table.value_1 FROM public.users_table ORDER BY users_table.value_1 LIMIT 3)))) SELECT dist_cte.user_id FROM (local_cte JOIN dist_cte ON ((dist_cte.user_id = local_cte.user_id))) +DEBUG: generating subplan 38_1 for CTE local_cte: SELECT user_id, "time", value_1, value_2, value_3, value_4 FROM subquery_and_ctes.users_table_local +DEBUG: generating subplan 38_2 for CTE dist_cte: SELECT events_table.user_id FROM public.events_table, (SELECT DISTINCT users_table.value_2 FROM public.users_table OFFSET 0) foo WHERE ((events_table.user_id = foo.value_2) AND (events_table.user_id IN (SELECT DISTINCT users_table.value_1 FROM public.users_table ORDER BY users_table.value_1 LIMIT 3))) DEBUG: push down of limit count: 3 -DEBUG: generating subplan 38_1 for subquery SELECT DISTINCT value_1 FROM public.users_table ORDER BY value_1 LIMIT 3 -DEBUG: generating subplan 38_2 for subquery SELECT DISTINCT value_2 FROM public.users_table OFFSET 0 -DEBUG: Plan 38 query after replacing subqueries and CTEs: SELECT events_table.user_id FROM public.events_table, (SELECT intermediate_result.value_2 FROM read_intermediate_result('38_2'::text, 'binary'::citus_copy_format) intermediate_result(value_2 integer)) foo WHERE ((events_table.user_id = foo.value_2) AND (events_table.user_id IN (SELECT intermediate_result.value_1 FROM read_intermediate_result('38_1'::text, 'binary'::citus_copy_format) intermediate_result(value_1 integer)))) -DEBUG: Plan 37 query after replacing subqueries and CTEs: SELECT dist_cte.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('37_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)) local_cte JOIN (SELECT intermediate_result.user_id FROM read_intermediate_result('37_2'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) dist_cte ON ((dist_cte.user_id = local_cte.user_id))) +DEBUG: generating subplan 39_1 for subquery SELECT DISTINCT value_1 FROM public.users_table ORDER BY value_1 LIMIT 3 +DEBUG: generating subplan 39_2 for subquery SELECT DISTINCT value_2 FROM public.users_table OFFSET 0 +DEBUG: Plan 39 query after replacing subqueries and CTEs: SELECT events_table.user_id FROM public.events_table, (SELECT intermediate_result.value_2 FROM read_intermediate_result('39_2'::text, 'binary'::citus_copy_format) intermediate_result(value_2 integer)) foo WHERE ((events_table.user_id = foo.value_2) AND (events_table.user_id IN (SELECT intermediate_result.value_1 FROM read_intermediate_result('39_1'::text, 'binary'::citus_copy_format) intermediate_result(value_1 integer)))) +DEBUG: Plan 38 query after replacing subqueries and CTEs: SELECT dist_cte.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('38_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)) local_cte JOIN (SELECT intermediate_result.user_id FROM read_intermediate_result('38_2'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) dist_cte ON ((dist_cte.user_id = local_cte.user_id))) DEBUG: push down of limit count: 5 -DEBUG: generating subplan 36_2 for subquery SELECT DISTINCT users_table.user_id FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.user_id) AND (events_table.event_type = ANY (ARRAY[1, 2, 3, 4]))) ORDER BY users_table.user_id DESC LIMIT 5 -DEBUG: generating subplan 36_3 for subquery SELECT count(*) AS cnt FROM (SELECT intermediate_result.user_id FROM read_intermediate_result('36_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) cte, (SELECT intermediate_result.user_id FROM read_intermediate_result('36_2'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) foo WHERE (foo.user_id = cte.user_id) -DEBUG: Plan 36 query after replacing subqueries and CTEs: SELECT foo.cnt, users_table.user_id, users_table."time", users_table.value_1, users_table.value_2, users_table.value_3, users_table.value_4 FROM (SELECT intermediate_result.cnt FROM read_intermediate_result('36_3'::text, 'binary'::citus_copy_format) intermediate_result(cnt bigint)) foo, public.users_table WHERE (foo.cnt > users_table.value_2) ORDER BY users_table."time" DESC, foo.cnt DESC, users_table.user_id DESC, users_table.value_1 DESC LIMIT 5 +DEBUG: generating subplan 37_2 for subquery SELECT DISTINCT users_table.user_id FROM public.users_table, public.events_table WHERE ((users_table.user_id = events_table.user_id) AND (events_table.event_type = ANY (ARRAY[1, 2, 3, 4]))) ORDER BY users_table.user_id DESC LIMIT 5 +DEBUG: generating subplan 37_3 for subquery SELECT count(*) AS cnt FROM (SELECT intermediate_result.user_id FROM read_intermediate_result('37_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) cte, (SELECT intermediate_result.user_id FROM read_intermediate_result('37_2'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) foo WHERE (foo.user_id = cte.user_id) +DEBUG: Plan 37 query after replacing subqueries and CTEs: SELECT foo.cnt, users_table.user_id, users_table."time", users_table.value_1, users_table.value_2, users_table.value_3, users_table.value_4 FROM (SELECT intermediate_result.cnt FROM read_intermediate_result('37_3'::text, 'binary'::citus_copy_format) intermediate_result(cnt bigint)) foo, public.users_table WHERE (foo.cnt > users_table.value_2) ORDER BY users_table."time" DESC, foo.cnt DESC, users_table.user_id DESC, users_table.value_1 DESC LIMIT 5 DEBUG: push down of limit count: 5 cnt | user_id | time | value_1 | value_2 | value_3 | value_4 -----+---------+---------------------------------+---------+---------+---------+--------- diff --git a/src/test/regress/expected/subquery_basics.out b/src/test/regress/expected/subquery_basics.out index e6f39da79..8a5bd5a30 100644 --- a/src/test/regress/expected/subquery_basics.out +++ b/src/test/regress/expected/subquery_basics.out @@ -422,3 +422,25 @@ DEBUG: Plan 26 query after replacing subqueries and CTEs: SELECT user_id FROM p 3 (2 rows) +-- we support queries with recurring tuples in the FROM +-- clause and subquery in WHERE clause +SELECT + * +FROM + ( + SELECT + users_table.user_id + FROM + users_table, (SELECT user_id FROM events_table) as evs + WHERE users_table.user_id = evs.user_id + ORDER BY 1 + LIMIT 5 + ) as foo WHERE user_id IN (SELECT count(*) FROM users_table GROUP BY user_id); +DEBUG: push down of limit count: 5 +DEBUG: generating subplan 28_1 for subquery SELECT users_table.user_id FROM public.users_table, (SELECT events_table.user_id FROM public.events_table) evs WHERE (users_table.user_id = evs.user_id) ORDER BY users_table.user_id LIMIT 5 +DEBUG: generating subplan 28_2 for subquery SELECT count(*) AS count FROM public.users_table GROUP BY user_id +DEBUG: Plan 28 query after replacing subqueries and CTEs: SELECT user_id FROM (SELECT intermediate_result.user_id FROM read_intermediate_result('28_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) foo WHERE (user_id IN (SELECT intermediate_result.count FROM read_intermediate_result('28_2'::text, 'binary'::citus_copy_format) intermediate_result(count bigint))) + user_id +--------- +(0 rows) + diff --git a/src/test/regress/expected/subquery_in_where.out b/src/test/regress/expected/subquery_in_where.out new file mode 100644 index 000000000..2212666da --- /dev/null +++ b/src/test/regress/expected/subquery_in_where.out @@ -0,0 +1,691 @@ +-- =================================================================== +-- test recursive planning functionality with subqueries in WHERE +-- =================================================================== +CREATE SCHEMA subquery_in_where; +SET search_path TO subquery_in_where, public; +SET client_min_messages TO DEBUG1; +--CTEs can be used as a recurring tuple with subqueries in WHERE +WITH event_id + AS (SELECT user_id AS events_user_id, + time AS events_time, + event_type + FROM events_table) +SELECT Count(*) +FROM event_id +WHERE events_user_id IN (SELECT user_id + FROM users_table); +DEBUG: generating subplan 1_1 for CTE event_id: SELECT user_id AS events_user_id, "time" AS events_time, event_type FROM public.events_table +DEBUG: generating subplan 1_2 for subquery SELECT user_id FROM public.users_table +DEBUG: Plan 1 query after replacing subqueries and CTEs: SELECT count(*) AS count FROM (SELECT intermediate_result.events_user_id, intermediate_result.events_time, intermediate_result.event_type FROM read_intermediate_result('1_1'::text, 'binary'::citus_copy_format) intermediate_result(events_user_id integer, events_time timestamp without time zone, event_type integer)) event_id WHERE (events_user_id IN (SELECT intermediate_result.user_id FROM read_intermediate_result('1_2'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer))) + count +------- + 101 +(1 row) + +--Correlated subqueries can not be used in WHERE clause +WITH event_id + AS (SELECT user_id AS events_user_id, + time AS events_time, + event_type + FROM events_table) +SELECT Count(*) +FROM event_id +WHERE events_user_id IN (SELECT user_id + FROM users_table + WHERE users_table.time = events_time); +DEBUG: generating subplan 4_1 for CTE event_id: SELECT user_id AS events_user_id, "time" AS events_time, event_type FROM public.events_table +DEBUG: Plan 4 query after replacing subqueries and CTEs: SELECT count(*) AS count FROM (SELECT intermediate_result.events_user_id, intermediate_result.events_time, intermediate_result.event_type FROM read_intermediate_result('4_1'::text, 'binary'::citus_copy_format) intermediate_result(events_user_id integer, events_time timestamp without time zone, event_type integer)) event_id WHERE (events_user_id IN (SELECT users_table.user_id FROM public.users_table WHERE (users_table."time" = event_id.events_time))) +ERROR: cannot pushdown the subquery +DETAIL: Complex subqueries and CTEs are not allowed in the FROM clause when the query has subqueries in the WHERE clause and it references a column from another query +-- Recurring tuples as empty join tree +SELECT * +FROM (SELECT 1 AS id, + 2 AS value_1, + 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 IN (SELECT intermediate_result.user_id FROM read_intermediate_result('6_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer))) + id | value_1 | value_3 +----+---------+--------- + 1 | 2 | 3 +(1 row) + +-- Recurring tuples in from clause as CTE and SET operation in WHERE clause +SELECT Count(*) +FROM (WITH event_id AS + (SELECT user_id AS events_user_id, time AS events_time, event_type + FROM events_table) + SELECT events_user_id, events_time, event_type + FROM event_id + ORDER BY 1,2,3 + LIMIT 10) AS sub_table +WHERE events_user_id IN ( + (SELECT user_id + FROM users_table + ORDER BY 1 + LIMIT 10) + UNION ALL + (SELECT value_1 + FROM users_table + ORDER BY 1 + limit 10)); +DEBUG: push down of limit count: 10 +DEBUG: generating subplan 8_1 for subquery SELECT user_id FROM public.users_table ORDER BY user_id LIMIT 10 +DEBUG: push down of limit count: 10 +DEBUG: generating subplan 8_2 for subquery SELECT value_1 FROM public.users_table ORDER BY value_1 LIMIT 10 +DEBUG: generating subplan 8_3 for subquery SELECT intermediate_result.user_id FROM read_intermediate_result('8_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer) UNION ALL SELECT intermediate_result.value_1 FROM read_intermediate_result('8_2'::text, 'binary'::citus_copy_format) intermediate_result(value_1 integer) +DEBUG: generating subplan 8_4 for CTE event_id: SELECT user_id AS events_user_id, "time" AS events_time, event_type FROM public.events_table +DEBUG: generating subplan 8_5 for subquery SELECT events_user_id, events_time, event_type FROM (SELECT intermediate_result.events_user_id, intermediate_result.events_time, intermediate_result.event_type FROM read_intermediate_result('8_4'::text, 'binary'::citus_copy_format) intermediate_result(events_user_id integer, events_time timestamp without time zone, event_type integer)) event_id ORDER BY events_user_id, events_time, event_type LIMIT 10 +DEBUG: Plan 8 query after replacing subqueries and CTEs: SELECT count(*) AS count FROM (SELECT intermediate_result.events_user_id, intermediate_result.events_time, intermediate_result.event_type FROM read_intermediate_result('8_5'::text, 'binary'::citus_copy_format) intermediate_result(events_user_id integer, events_time timestamp without time zone, event_type integer)) sub_table WHERE (events_user_id IN (SELECT intermediate_result.user_id FROM read_intermediate_result('8_3'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer))) + count +------- + 10 +(1 row) + +-- Recurring tuples in from clause as SET operation on recursively plannable +-- queries and CTE in WHERE clause +SELECT + * +FROM + ( + (SELECT + user_id + FROM + users_table + ORDER BY + user_id ASC + LIMIT + 10 + ) + UNION ALL + (SELECT + value_1 + FROM + users_table + ORDER BY + value_1 ASC + LIMIT + 10 + ) + ) as SUB_TABLE +WHERE + user_id +IN + ( + WITH event_id AS ( + SELECT + user_id as events_user_id, time as events_time, event_type + FROM + events_table + ) + SELECT + events_user_id + FROM + event_id + ORDER BY + events_user_id + LIMIT + 10 + ); +DEBUG: generating subplan 14_1 for CTE event_id: SELECT user_id AS events_user_id, "time" AS events_time, event_type FROM public.events_table +DEBUG: generating subplan 14_2 for subquery SELECT events_user_id FROM (SELECT intermediate_result.events_user_id, intermediate_result.events_time, intermediate_result.event_type FROM read_intermediate_result('14_1'::text, 'binary'::citus_copy_format) intermediate_result(events_user_id integer, events_time timestamp without time zone, event_type integer)) event_id ORDER BY events_user_id LIMIT 10 +DEBUG: push down of limit count: 10 +DEBUG: generating subplan 14_3 for subquery SELECT user_id FROM public.users_table ORDER BY user_id LIMIT 10 +DEBUG: push down of limit count: 10 +DEBUG: generating subplan 14_4 for subquery SELECT value_1 FROM public.users_table ORDER BY value_1 LIMIT 10 +DEBUG: generating subplan 14_5 for subquery SELECT intermediate_result.user_id FROM read_intermediate_result('14_3'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer) UNION ALL SELECT intermediate_result.value_1 FROM read_intermediate_result('14_4'::text, 'binary'::citus_copy_format) intermediate_result(value_1 integer) +DEBUG: Plan 14 query after replacing subqueries and CTEs: SELECT user_id FROM (SELECT intermediate_result.user_id FROM read_intermediate_result('14_5'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) sub_table WHERE (user_id IN (SELECT intermediate_result.events_user_id FROM read_intermediate_result('14_2'::text, 'binary'::citus_copy_format) intermediate_result(events_user_id integer))) + user_id +--------- + 1 + 1 + 1 + 1 + 1 + 1 + 1 +(7 rows) + +-- Complex target list in WHERE clause +SELECT + COUNT(*) +FROM + (SELECT + user_id as events_user_id, time as events_time, event_type + FROM + events_table + ORDER BY + 1,2 + LIMIT + 10 + ) as SUB_TABLE +WHERE + events_user_id +<=ANY ( + SELECT + max(abs(user_id * 1) + mod(user_id, 3)) as val_1 + FROM + users_table + GROUP BY + user_id +); +DEBUG: push down of limit count: 10 +DEBUG: generating subplan 20_1 for subquery SELECT user_id AS events_user_id, "time" AS events_time, event_type FROM public.events_table ORDER BY user_id, "time" LIMIT 10 +DEBUG: generating subplan 20_2 for subquery SELECT max((abs((user_id * 1)) + mod(user_id, 3))) AS val_1 FROM public.users_table GROUP BY user_id +DEBUG: Plan 20 query after replacing subqueries and CTEs: SELECT count(*) AS count FROM (SELECT intermediate_result.events_user_id, intermediate_result.events_time, intermediate_result.event_type FROM read_intermediate_result('20_1'::text, 'binary'::citus_copy_format) intermediate_result(events_user_id integer, events_time timestamp without time zone, event_type integer)) sub_table WHERE (events_user_id <= ANY (SELECT intermediate_result.val_1 FROM read_intermediate_result('20_2'::text, 'binary'::citus_copy_format) intermediate_result(val_1 integer))) + count +------- + 10 +(1 row) + +-- DISTINCT clause in WHERE +SELECT + COUNT(*) +FROM + (SELECT + user_id as events_user_id, time as events_time, event_type + FROM + events_table + LIMIT + 10 + ) as SUB_TABLE +WHERE + events_user_id +IN ( + SELECT + distinct user_id + FROM + users_table + GROUP BY + user_id +); +DEBUG: push down of limit count: 10 +DEBUG: generating subplan 23_1 for subquery SELECT user_id AS events_user_id, "time" AS events_time, event_type FROM public.events_table LIMIT 10 +DEBUG: generating subplan 23_2 for subquery SELECT DISTINCT user_id FROM public.users_table GROUP BY user_id +DEBUG: Plan 23 query after replacing subqueries and CTEs: SELECT count(*) AS count FROM (SELECT intermediate_result.events_user_id, intermediate_result.events_time, intermediate_result.event_type FROM read_intermediate_result('23_1'::text, 'binary'::citus_copy_format) intermediate_result(events_user_id integer, events_time timestamp without time zone, event_type integer)) sub_table WHERE (events_user_id IN (SELECT intermediate_result.user_id FROM read_intermediate_result('23_2'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer))) + count +------- + 10 +(1 row) + +-- AND in WHERE clause +SELECT + COUNT(*) +FROM + (SELECT + user_id as events_user_id, time as events_time, event_type + FROM + events_table + ORDER BY + 1,2,3 + LIMIT + 10 + ) as SUB_TABLE +WHERE + events_user_id +>=ANY ( + SELECT + min(user_id) + FROM + users_table + GROUP BY + user_id +) +AND + events_user_id +<=ANY ( + SELECT + max(user_id) + FROM + users_table + GROUP BY + user_id +); +DEBUG: push down of limit count: 10 +DEBUG: generating subplan 26_1 for subquery SELECT user_id AS events_user_id, "time" AS events_time, event_type FROM public.events_table ORDER BY user_id, "time", event_type LIMIT 10 +DEBUG: generating subplan 26_2 for subquery SELECT min(user_id) AS min FROM public.users_table GROUP BY user_id +DEBUG: generating subplan 26_3 for subquery SELECT max(user_id) AS max FROM public.users_table GROUP BY user_id +DEBUG: Plan 26 query after replacing subqueries and CTEs: SELECT count(*) AS count FROM (SELECT intermediate_result.events_user_id, intermediate_result.events_time, intermediate_result.event_type FROM read_intermediate_result('26_1'::text, 'binary'::citus_copy_format) intermediate_result(events_user_id integer, events_time timestamp without time zone, event_type integer)) sub_table WHERE ((events_user_id >= ANY (SELECT intermediate_result.min FROM read_intermediate_result('26_2'::text, 'binary'::citus_copy_format) intermediate_result(min integer))) AND (events_user_id <= ANY (SELECT intermediate_result.max FROM read_intermediate_result('26_3'::text, 'binary'::citus_copy_format) intermediate_result(max integer)))) + count +------- + 10 +(1 row) + +-- AND in WHERE clause, part of the AND is pushdownable other is not +SELECT + COUNT(*) +FROM + (SELECT + user_id as events_user_id, time as events_time, event_type + FROM + events_table + ORDER BY + 1,2,3 + LIMIT + 10 + ) as SUB_TABLE +WHERE + events_user_id +>=ANY ( + SELECT + min(user_id) + FROM + users_table + GROUP BY + user_id +) +AND + events_user_id +<=ANY ( + SELECT + max(value_2) + FROM + users_table + GROUP BY + user_id +); +DEBUG: push down of limit count: 10 +DEBUG: generating subplan 30_1 for subquery SELECT user_id AS events_user_id, "time" AS events_time, event_type FROM public.events_table ORDER BY user_id, "time", event_type LIMIT 10 +DEBUG: generating subplan 30_2 for subquery SELECT min(user_id) AS min FROM public.users_table GROUP BY user_id +DEBUG: generating subplan 30_3 for subquery SELECT max(value_2) AS max FROM public.users_table GROUP BY user_id +DEBUG: Plan 30 query after replacing subqueries and CTEs: SELECT count(*) AS count FROM (SELECT intermediate_result.events_user_id, intermediate_result.events_time, intermediate_result.event_type FROM read_intermediate_result('30_1'::text, 'binary'::citus_copy_format) intermediate_result(events_user_id integer, events_time timestamp without time zone, event_type integer)) sub_table WHERE ((events_user_id >= ANY (SELECT intermediate_result.min FROM read_intermediate_result('30_2'::text, 'binary'::citus_copy_format) intermediate_result(min integer))) AND (events_user_id <= ANY (SELECT intermediate_result.max FROM read_intermediate_result('30_3'::text, 'binary'::citus_copy_format) intermediate_result(max integer)))) + count +------- + 10 +(1 row) + +-- Planning subqueries in WHERE clause in CTE recursively +WITH cte AS ( + SELECT + * + FROM + (SELECT + * + FROM + users_table + ORDER BY + user_id ASC, + value_2 DESC + LIMIT + 10 + ) as sub_table + WHERE + user_id + IN + (SELECT + value_2 + FROM + events_table + ) +) +SELECT + COUNT(*) +FROM + cte; +DEBUG: generating subplan 34_1 for CTE cte: SELECT user_id, "time", value_1, value_2, value_3, value_4 FROM (SELECT users_table.user_id, users_table."time", users_table.value_1, users_table.value_2, users_table.value_3, users_table.value_4 FROM public.users_table ORDER BY users_table.user_id, users_table.value_2 DESC LIMIT 10) sub_table WHERE (user_id IN (SELECT events_table.value_2 FROM public.events_table)) +DEBUG: push down of limit count: 10 +DEBUG: generating subplan 35_1 for subquery SELECT user_id, "time", value_1, value_2, value_3, value_4 FROM public.users_table ORDER BY user_id, value_2 DESC LIMIT 10 +DEBUG: generating subplan 35_2 for subquery SELECT value_2 FROM public.events_table +DEBUG: Plan 35 query after replacing subqueries and CTEs: SELECT user_id, "time", value_1, value_2, value_3, value_4 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('35_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)) sub_table WHERE (user_id IN (SELECT intermediate_result.value_2 FROM read_intermediate_result('35_2'::text, 'binary'::citus_copy_format) intermediate_result(value_2 integer))) +DEBUG: Plan 34 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('34_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)) cte + count +------- + 10 +(1 row) + +-- Planing subquery in WHERE clause in FROM clause of a subquery recursively +SELECT + COUNT(*) +FROM + (SELECT + * + FROM + (SELECT + * + FROM + users_table + ORDER BY + user_id ASC, + value_2 DESC + LIMIT + 10 + ) as sub_table_1 + WHERE + user_id + IN + (SELECT + value_2 + FROM + events_table + ) + ) as sub_table_2; +DEBUG: push down of limit count: 10 +DEBUG: generating subplan 38_1 for subquery SELECT user_id, "time", value_1, value_2, value_3, value_4 FROM public.users_table ORDER BY user_id, value_2 DESC LIMIT 10 +DEBUG: generating subplan 38_2 for subquery SELECT value_2 FROM public.events_table +DEBUG: generating subplan 38_3 for subquery SELECT user_id, "time", value_1, value_2, value_3, value_4 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('38_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)) sub_table_1 WHERE (user_id IN (SELECT intermediate_result.value_2 FROM read_intermediate_result('38_2'::text, 'binary'::citus_copy_format) intermediate_result(value_2 integer))) +DEBUG: Plan 38 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('38_3'::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_2 + count +------- + 10 +(1 row) + +-- Recurring table in the FROM clause of a subquery in the FROM clause +-- Recurring table is created by joining a two recurrign table +SELECT + SUM(user_id) +FROM + (SELECT + * + FROM + (SELECT + user_id + FROM + users_table + ORDER BY + user_id + LIMIT 10) as t1 + INNER JOIN + (SELECT + user_id as user_id_2 + FROM + users_table + ORDER BY + user_id + LIMIT + 10) as t2 + ON + t1.user_id = t2.user_id_2 + WHERE + t1.user_id + IN + (SELECT + value_2 + FROM + events_table) + ) as t3 +WHERE + user_id +>ANY + (SELECT + min(user_id) + FROM + events_table + GROUP BY + user_id); +DEBUG: push down of limit count: 10 +DEBUG: generating subplan 42_1 for subquery SELECT user_id FROM public.users_table ORDER BY user_id LIMIT 10 +DEBUG: push down of limit count: 10 +DEBUG: generating subplan 42_2 for subquery SELECT user_id AS user_id_2 FROM public.users_table ORDER BY user_id LIMIT 10 +DEBUG: generating subplan 42_3 for subquery SELECT value_2 FROM public.events_table +DEBUG: generating subplan 42_4 for subquery SELECT t1.user_id, t2.user_id_2 FROM ((SELECT intermediate_result.user_id FROM read_intermediate_result('42_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) t1 JOIN (SELECT intermediate_result.user_id_2 FROM read_intermediate_result('42_2'::text, 'binary'::citus_copy_format) intermediate_result(user_id_2 integer)) t2 ON ((t1.user_id = t2.user_id_2))) WHERE (t1.user_id IN (SELECT intermediate_result.value_2 FROM read_intermediate_result('42_3'::text, 'binary'::citus_copy_format) intermediate_result(value_2 integer))) +DEBUG: generating subplan 42_5 for subquery SELECT min(user_id) AS min FROM public.events_table GROUP BY user_id +DEBUG: Plan 42 query after replacing subqueries and CTEs: SELECT sum(user_id) AS sum FROM (SELECT intermediate_result.user_id, intermediate_result.user_id_2 FROM read_intermediate_result('42_4'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer, user_id_2 integer)) t3 WHERE (user_id > ANY (SELECT intermediate_result.min FROM read_intermediate_result('42_5'::text, 'binary'::citus_copy_format) intermediate_result(min integer))) + sum +----- + 18 +(1 row) + +-- Same example with the above query, but now check the rows with EXISTS +SELECT + SUM(user_id) +FROM + (SELECT + * + FROM + (SELECT + user_id + FROM + users_table + ORDER BY + user_id + LIMIT 10) as t1 + INNER JOIN + (SELECT + user_id as user_id_2 + FROM + users_table + ORDER BY + user_id + LIMIT + 10) as t2 + ON + t1.user_id = t2.user_id_2 + WHERE + t1.user_id + IN + (SELECT + value_2 + FROM + events_table) + ) as t3 +WHERE EXISTS + (SELECT + 1,2 + FROM + events_table + WHERE + events_table.value_2 = events_table.user_id); +DEBUG: push down of limit count: 10 +DEBUG: generating subplan 48_1 for subquery SELECT user_id FROM public.users_table ORDER BY user_id LIMIT 10 +DEBUG: push down of limit count: 10 +DEBUG: generating subplan 48_2 for subquery SELECT user_id AS user_id_2 FROM public.users_table ORDER BY user_id LIMIT 10 +DEBUG: generating subplan 48_3 for subquery SELECT value_2 FROM public.events_table +DEBUG: generating subplan 48_4 for subquery SELECT t1.user_id, t2.user_id_2 FROM ((SELECT intermediate_result.user_id FROM read_intermediate_result('48_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) t1 JOIN (SELECT intermediate_result.user_id_2 FROM read_intermediate_result('48_2'::text, 'binary'::citus_copy_format) intermediate_result(user_id_2 integer)) t2 ON ((t1.user_id = t2.user_id_2))) WHERE (t1.user_id IN (SELECT intermediate_result.value_2 FROM read_intermediate_result('48_3'::text, 'binary'::citus_copy_format) intermediate_result(value_2 integer))) +DEBUG: generating subplan 48_5 for subquery SELECT 1, 2 FROM public.events_table WHERE (value_2 = user_id) +DEBUG: Plan 48 query after replacing subqueries and CTEs: SELECT sum(user_id) AS sum FROM (SELECT intermediate_result.user_id, intermediate_result.user_id_2 FROM read_intermediate_result('48_4'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer, user_id_2 integer)) t3 WHERE (EXISTS (SELECT intermediate_result."?column?", intermediate_result."?column?_1" AS "?column?" FROM read_intermediate_result('48_5'::text, 'binary'::citus_copy_format) intermediate_result("?column?" integer, "?column?_1" integer))) + sum +----- + 67 +(1 row) + +-- Same query with the above one, yet now we check the row's NON-existence +-- by NOT EXISTS. Note that, max value_2 of events_table is 5 +SELECT + SUM(user_id) +FROM + (SELECT + * + FROM + (SELECT + user_id + FROM + users_table + ORDER BY + user_id + LIMIT 10) as t1 + INNER JOIN + (SELECT + user_id as user_id_2 + FROM + users_table + ORDER BY + user_id + LIMIT + 10) as t2 + ON + t1.user_id = t2.user_id_2 + WHERE + t1.user_id + IN + (SELECT + value_2 + FROM + events_table) + ) as t3 +WHERE NOT EXISTS + (SELECT + 1,2 + FROM + events_table + WHERE + events_table.value_2 = events_table.user_id + 6); +DEBUG: push down of limit count: 10 +DEBUG: generating subplan 54_1 for subquery SELECT user_id FROM public.users_table ORDER BY user_id LIMIT 10 +DEBUG: push down of limit count: 10 +DEBUG: generating subplan 54_2 for subquery SELECT user_id AS user_id_2 FROM public.users_table ORDER BY user_id LIMIT 10 +DEBUG: generating subplan 54_3 for subquery SELECT value_2 FROM public.events_table +DEBUG: generating subplan 54_4 for subquery SELECT t1.user_id, t2.user_id_2 FROM ((SELECT intermediate_result.user_id FROM read_intermediate_result('54_1'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer)) t1 JOIN (SELECT intermediate_result.user_id_2 FROM read_intermediate_result('54_2'::text, 'binary'::citus_copy_format) intermediate_result(user_id_2 integer)) t2 ON ((t1.user_id = t2.user_id_2))) WHERE (t1.user_id IN (SELECT intermediate_result.value_2 FROM read_intermediate_result('54_3'::text, 'binary'::citus_copy_format) intermediate_result(value_2 integer))) +DEBUG: generating subplan 54_5 for subquery SELECT 1, 2 FROM public.events_table WHERE (value_2 = (user_id + 6)) +DEBUG: Plan 54 query after replacing subqueries and CTEs: SELECT sum(user_id) AS sum FROM (SELECT intermediate_result.user_id, intermediate_result.user_id_2 FROM read_intermediate_result('54_4'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer, user_id_2 integer)) t3 WHERE (NOT (EXISTS (SELECT intermediate_result."?column?", intermediate_result."?column?_1" AS "?column?" FROM read_intermediate_result('54_5'::text, 'binary'::citus_copy_format) intermediate_result("?column?" integer, "?column?_1" integer)))) + sum +----- + 67 +(1 row) + +-- Check the existence of row by comparing it with the result of subquery in +-- WHERE clause. Note that subquery is planned recursively since there is no +-- distributed table in the from +SELECT + * +FROM + (SELECT + user_id, value_1 + FROM + users_table + ORDER BY + user_id ASC, + value_1 ASC + LIMIT 10) as t3 +WHERE row(user_id, value_1) = + (SELECT + min(user_id) + 1, min(user_id) + 1 + FROM + events_table); +DEBUG: generating subplan 60_1 for subquery SELECT (min(user_id) + 1), (min(user_id) + 1) FROM public.events_table +DEBUG: push down of limit count: 10 +DEBUG: generating subplan 60_2 for subquery SELECT user_id, value_1 FROM public.users_table ORDER BY user_id, value_1 LIMIT 10 +DEBUG: Plan 60 query after replacing subqueries and CTEs: SELECT user_id, value_1 FROM (SELECT intermediate_result.user_id, intermediate_result.value_1 FROM read_intermediate_result('60_2'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer, value_1 integer)) t3 WHERE ((user_id, value_1) = (SELECT intermediate_result."?column?", intermediate_result."?column?_1" AS "?column?" FROM read_intermediate_result('60_1'::text, 'binary'::citus_copy_format) intermediate_result("?column?" integer, "?column?_1" integer))) + user_id | value_1 +---------+--------- +(0 rows) + +-- Recursively plan subquery in WHERE clause when the FROM clause has a subquery +-- generated by generate_series function +SELECT + * +FROM + (SELECT + * + FROM + generate_series(1,10) + ) as gst +WHERE + generate_series +IN + (SELECT + value_2 + FROM + events_table + ) +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 IN (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 + generate_series +----------------- + 1 + 2 + 3 + 4 + 5 +(5 rows) + +-- Similar to the test above, now we also have a generate_series in WHERE clause +SELECT + * +FROM + (SELECT + * + FROM + generate_series(1,10) + ) as gst +WHERE + generate_series +IN + (SELECT + user_id + FROM + users_table + WHERE + user_id + IN + (SELECT + * + FROM + generate_series(1,3) + ) + ) +ORDER BY + generate_series ASC; +DEBUG: generating subplan 65_1 for subquery SELECT user_id FROM public.users_table WHERE (user_id IN (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 IN (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 + generate_series +----------------- + 1 + 2 + 3 +(3 rows) + + +-- 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); +INSERT INTO local_table VALUES(1,1), (2,2); +SELECT + * +FROM + (SELECT + * + FROM + local_table) as sub_table +WHERE + id +IN + (SELECT + 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 IN (SELECT intermediate_result.user_id FROM read_intermediate_result('67_2'::text, 'binary'::citus_copy_format) intermediate_result(user_id integer))) + id | value_1 +----+--------- + 1 | 1 + 2 | 2 +(2 rows) + + +-- Use local table in WHERE clause +SELECT + COUNT(*) +FROM + (SELECT + * + FROM + users_table + ORDER BY + user_id + LIMIT + 10) as sub_table +WHERE + user_id +IN + (SELECT + id + FROM + local_table); +DEBUG: generating subplan 69_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 IN (SELECT intermediate_result.id FROM read_intermediate_result('69_1'::text, 'binary'::citus_copy_format) intermediate_result(id integer))) + count +------- + 10 +(1 row) + +DROP TABLE local_table; +DEBUG: EventTriggerInvoke 19921 +SET client_min_messages TO DEFAULT; +DROP SCHEMA subquery_in_where CASCADE; +SET search_path TO public; diff --git a/src/test/regress/expected/with_prepare.out b/src/test/regress/expected/with_prepare.out index 629607c72..6efdaf68f 100644 --- a/src/test/regress/expected/with_prepare.out +++ b/src/test/regress/expected/with_prepare.out @@ -174,6 +174,18 @@ FROM ORDER BY 1, 2, 3, 4, 5, 6 LIMIT 10; +-- Prepare a statement with a sublink in WHERE clause and recurring tuple in FORM +PREPARE prepared_test_6 AS +WITH event_id AS ( + SELECT user_id as events_user_id, time as events_time, event_type + FROM events_table +) +SELECT + count(*) +FROM + event_id +WHERE + events_user_id IN (SELECT user_id FROM users_table); EXECUTE prepared_test_1; user_id | time | value_1 | value_2 | value_3 | value_4 ---------+---------------------------------+---------+---------+---------+--------- @@ -542,6 +554,42 @@ EXECUTE prepared_test_5(6, 7, 8); 6 | Thu Nov 23 14:43:18.024104 2017 | 3 | 2 | 5 | (10 rows) +EXECUTE prepared_test_6; + count +------- + 101 +(1 row) + +EXECUTE prepared_test_6; + count +------- + 101 +(1 row) + +EXECUTE prepared_test_6; + count +------- + 101 +(1 row) + +EXECUTE prepared_test_6; + count +------- + 101 +(1 row) + +EXECUTE prepared_test_6; + count +------- + 101 +(1 row) + +EXECUTE prepared_test_6; + count +------- + 101 +(1 row) + EXECUTE prepared_partition_column_insert(1); ERROR: data-modifying statements are not supported in the WITH clauses of distributed queries DEALLOCATE ALL; diff --git a/src/test/regress/multi_schedule b/src/test/regress/multi_schedule index 7c54faad7..cda1dea49 100644 --- a/src/test/regress/multi_schedule +++ b/src/test/regress/multi_schedule @@ -43,7 +43,7 @@ test: multi_partitioning_utils multi_partitioning # Tests for recursive subquery planning # ---------- test: subquery_basics subquery_local_tables subquery_executors subquery_and_cte set_operations set_operation_and_local_tables -test: subqueries_deep subquery_view subquery_partitioning subquery_complex_target_list subqueries_not_supported +test: subqueries_deep subquery_view subquery_partitioning subquery_complex_target_list subqueries_not_supported subquery_in_where test: subquery_prepared_statements # ---------- 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 8c1b48870..c5c5005f7 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,8 @@ GROUP BY user_id ORDER BY user_id LIMIT 3; --- subqueries in WHERE with NOT EXISTS operator, should not work --- there is a reference table in the outer part of the join +-- subqueries in WHERE with NOT EXISTS operator, should not work since +-- there is a correlated subquery in WHERE clause SELECT user_id FROM @@ -55,7 +55,8 @@ WHERE ) LIMIT 3; --- immutable functions are also treated as reference tables +-- immutable functions are also treated as reference tables, query should not +-- work since there is a correlated subquery in the WHERE clause SELECT user_id FROM @@ -71,7 +72,8 @@ WHERE ) LIMIT 3; --- subqueries without FROM are also treated as reference tables +-- subqueries without FROM are also treated as reference tables, query should not +-- work since there is a correlated subquery in the WHERE clause SELECT user_id FROM @@ -353,7 +355,10 @@ SELECT user_id, value_2 FROM users_table WHERE ) ORDER BY 1, 2; --- reference tables are not allowed if there is sublink +-- change debug level to check recursive planning output +SET client_min_messages TO DEBUG1; + +-- recursively planning subqueries in WHERE clause due to recurring table in FROM SELECT count(*) FROM @@ -362,8 +367,7 @@ 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); - --- reference tables are not allowed if there is sublink +-- recursively planning subqueries in WHERE clause due to recurring table in FROM SELECT count(*) FROM (SELECT @@ -373,7 +377,7 @@ FROM FROM users_table JOIN users_reference_table AS u2 ON users_table.value_2 = u2.value_2); --- reference tables are not allowed if there is sublink +-- query should not work since there is a correlated subquery in the WHERE clause SELECT user_id, count(*) FROM users_reference_table @@ -388,8 +392,7 @@ ORDER BY 2 DESC, 1 DESC LIMIT 5; --- reference tables are not allowed if there is sublink --- this time in the subquery +-- query will be planned as a SEMI JOIN SELECT * FROM users_table WHERE user_id IN @@ -402,6 +405,8 @@ WHERE user_id IN ORDER BY 1,2,3 LIMIT 5; +SET client_min_messages TO DEFAULT; + -- not supported since GROUP BY references to an upper level query SELECT user_id diff --git a/src/test/regress/sql/set_operation_and_local_tables.sql b/src/test/regress/sql/set_operation_and_local_tables.sql index fa2ddd88d..a52dfb7b8 100644 --- a/src/test/regress/sql/set_operation_and_local_tables.sql +++ b/src/test/regress/sql/set_operation_and_local_tables.sql @@ -88,7 +88,7 @@ SELECT * FROM ((SELECT * FROM local_test) INTERSECT (SELECT * FROM test ORDER BY -- 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; --- distributed table in WHERE clause, but not FROM clause still disallowed +-- 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; SET citus.enable_repartition_joins TO ON; diff --git a/src/test/regress/sql/set_operations.sql b/src/test/regress/sql/set_operations.sql index 866ea9f8d..c911f3e00 100644 --- a/src/test/regress/sql/set_operations.sql +++ b/src/test/regress/sql/set_operations.sql @@ -97,7 +97,7 @@ SELECT * FROM ((SELECT * FROM test) UNION (SELECT * FROM test)) foo WHERE x IN ( -- now both the set operations and the sublink is recursively planned SELECT * FROM ((SELECT x,y FROM test) UNION (SELECT y,x FROM test)) foo WHERE x IN (SELECT y FROM test ORDER BY 1 LIMIT 4) ORDER BY 1; --- set operations are recursively planned and not the sublink, thus should error out +-- set operations and the sublink can be recursively planned SELECT * FROM ((SELECT x,y FROM test) UNION (SELECT y,x FROM test)) foo WHERE x IN (SELECT y FROM test) ORDER BY 1; -- set operations works fine with pushdownable window functions @@ -115,7 +115,7 @@ SELECT x, y, rnk FROM (SELECT *, rank() OVER my_win as rnk FROM test WINDOW my_w SELECT * FROM ((SELECT * FROM test) EXCEPT (SELECT * FROM test ORDER BY x LIMIT 1)) u JOIN test USING (x) ORDER BY 1,2; SELECT * FROM ((SELECT * FROM test) INTERSECT (SELECT * FROM test ORDER BY x LIMIT 1)) u LEFT JOIN test USING (x) ORDER BY 1,2; --- distributed table in WHERE clause, but not FROM clause still disallowed +-- distributed table in WHERE clause is recursively planned SELECT * FROM ((SELECT * FROM test) UNION (SELECT * FROM ref WHERE a IN (SELECT x FROM test))) u ORDER BY 1,2; -- subquery union in WHERE clause with partition column equality and implicit join is pushed down diff --git a/src/test/regress/sql/subqueries_not_supported.sql b/src/test/regress/sql/subqueries_not_supported.sql index 136117045..cdee91c68 100644 --- a/src/test/regress/sql/subqueries_not_supported.sql +++ b/src/test/regress/sql/subqueries_not_supported.sql @@ -58,20 +58,6 @@ FROM LIMIT 5 ) as foo; --- we don't support queries with recurring tuples in the FROM --- clause and subquery in WHERE clause -SELECT - * -FROM - ( - SELECT - users_table.user_id - FROM - users_table, (SELECT user_id FROM events_table) as evs - WHERE users_table.user_id = evs.user_id - LIMIT 5 - ) as foo WHERE user_id IN (SELECT count(*) FROM users_table GROUP BY user_id); - -- we don't support recursive subqueries when router executor is disabled SET citus.enable_router_execution TO false; SELECT diff --git a/src/test/regress/sql/subquery_and_cte.sql b/src/test/regress/sql/subquery_and_cte.sql index 3ec23cb39..1db65adc1 100644 --- a/src/test/regress/sql/subquery_and_cte.sql +++ b/src/test/regress/sql/subquery_and_cte.sql @@ -81,10 +81,8 @@ WHERE users_table.user_id IN (SELECT DISTINCT value_2 FROM users_table WHERE value_1 >= 1 AND value_1 <= 20 ORDER BY 1 LIMIT 5) ORDER BY 1 DESC; --- a very similar query as the above, but this time errors --- out since we don't support subqueries in WHERE clause --- when there is only intermediate results on the range table --- note that this time subquery in WHERE clause is not replaced +-- subquery in WHERE clause is planned recursively due to the recurring table +-- in FROM clause WITH cte AS ( WITH local_cte AS ( SELECT * FROM users_table_local diff --git a/src/test/regress/sql/subquery_basics.sql b/src/test/regress/sql/subquery_basics.sql index fe482a2d1..6caf7e77b 100644 --- a/src/test/regress/sql/subquery_basics.sql +++ b/src/test/regress/sql/subquery_basics.sql @@ -311,3 +311,17 @@ GROUP BY user_id HAVING count(*) > 1 AND sum(value_2) > 29 ORDER BY 1; +-- we support queries with recurring tuples in the FROM +-- clause and subquery in WHERE clause +SELECT + * +FROM + ( + SELECT + users_table.user_id + FROM + users_table, (SELECT user_id FROM events_table) as evs + WHERE users_table.user_id = evs.user_id + ORDER BY 1 + LIMIT 5 + ) as foo WHERE user_id IN (SELECT count(*) FROM users_table GROUP BY user_id); diff --git a/src/test/regress/sql/subquery_in_where.sql b/src/test/regress/sql/subquery_in_where.sql new file mode 100644 index 000000000..f4b12f1f8 --- /dev/null +++ b/src/test/regress/sql/subquery_in_where.sql @@ -0,0 +1,517 @@ +-- =================================================================== +-- test recursive planning functionality with subqueries in WHERE +-- =================================================================== +CREATE SCHEMA subquery_in_where; +SET search_path TO subquery_in_where, public; + +SET client_min_messages TO DEBUG1; + +--CTEs can be used as a recurring tuple with subqueries in WHERE +WITH event_id + AS (SELECT user_id AS events_user_id, + time AS events_time, + event_type + FROM events_table) +SELECT Count(*) +FROM event_id +WHERE events_user_id IN (SELECT user_id + FROM users_table); + +--Correlated subqueries can not be used in WHERE clause +WITH event_id + AS (SELECT user_id AS events_user_id, + time AS events_time, + event_type + FROM events_table) +SELECT Count(*) +FROM event_id +WHERE events_user_id IN (SELECT user_id + FROM users_table + WHERE users_table.time = events_time); + +-- Recurring tuples as empty join tree +SELECT * +FROM (SELECT 1 AS id, + 2 AS value_1, + 3 AS value_3) AS tt1 +WHERE id IN (SELECT user_id + FROM events_table); + +-- Recurring tuples in from clause as CTE and SET operation in WHERE clause +SELECT Count(*) +FROM (WITH event_id AS + (SELECT user_id AS events_user_id, time AS events_time, event_type + FROM events_table) + SELECT events_user_id, events_time, event_type + FROM event_id + ORDER BY 1,2,3 + LIMIT 10) AS sub_table +WHERE events_user_id IN ( + (SELECT user_id + FROM users_table + ORDER BY 1 + LIMIT 10) + UNION ALL + (SELECT value_1 + FROM users_table + ORDER BY 1 + limit 10)); + +-- Recurring tuples in from clause as SET operation on recursively plannable +-- queries and CTE in WHERE clause +SELECT + * +FROM + ( + (SELECT + user_id + FROM + users_table + ORDER BY + user_id ASC + LIMIT + 10 + ) + UNION ALL + (SELECT + value_1 + FROM + users_table + ORDER BY + value_1 ASC + LIMIT + 10 + ) + ) as SUB_TABLE +WHERE + user_id +IN + ( + WITH event_id AS ( + SELECT + user_id as events_user_id, time as events_time, event_type + FROM + events_table + ) + SELECT + events_user_id + FROM + event_id + ORDER BY + events_user_id + LIMIT + 10 + ); + +-- Complex target list in WHERE clause +SELECT + COUNT(*) +FROM + (SELECT + user_id as events_user_id, time as events_time, event_type + FROM + events_table + ORDER BY + 1,2 + LIMIT + 10 + ) as SUB_TABLE +WHERE + events_user_id +<=ANY ( + SELECT + max(abs(user_id * 1) + mod(user_id, 3)) as val_1 + FROM + users_table + GROUP BY + user_id +); + +-- DISTINCT clause in WHERE +SELECT + COUNT(*) +FROM + (SELECT + user_id as events_user_id, time as events_time, event_type + FROM + events_table + LIMIT + 10 + ) as SUB_TABLE +WHERE + events_user_id +IN ( + SELECT + distinct user_id + FROM + users_table + GROUP BY + user_id +); + +-- AND in WHERE clause +SELECT + COUNT(*) +FROM + (SELECT + user_id as events_user_id, time as events_time, event_type + FROM + events_table + ORDER BY + 1,2,3 + LIMIT + 10 + ) as SUB_TABLE +WHERE + events_user_id +>=ANY ( + SELECT + min(user_id) + FROM + users_table + GROUP BY + user_id +) +AND + events_user_id +<=ANY ( + SELECT + max(user_id) + FROM + users_table + GROUP BY + user_id +); + +-- AND in WHERE clause, part of the AND is pushdownable other is not +SELECT + COUNT(*) +FROM + (SELECT + user_id as events_user_id, time as events_time, event_type + FROM + events_table + ORDER BY + 1,2,3 + LIMIT + 10 + ) as SUB_TABLE +WHERE + events_user_id +>=ANY ( + SELECT + min(user_id) + FROM + users_table + GROUP BY + user_id +) +AND + events_user_id +<=ANY ( + SELECT + max(value_2) + FROM + users_table + GROUP BY + user_id +); + +-- Planning subqueries in WHERE clause in CTE recursively +WITH cte AS ( + SELECT + * + FROM + (SELECT + * + FROM + users_table + ORDER BY + user_id ASC, + value_2 DESC + LIMIT + 10 + ) as sub_table + WHERE + user_id + IN + (SELECT + value_2 + FROM + events_table + ) +) +SELECT + COUNT(*) +FROM + cte; + +-- Planing subquery in WHERE clause in FROM clause of a subquery recursively +SELECT + COUNT(*) +FROM + (SELECT + * + FROM + (SELECT + * + FROM + users_table + ORDER BY + user_id ASC, + value_2 DESC + LIMIT + 10 + ) as sub_table_1 + WHERE + user_id + IN + (SELECT + value_2 + FROM + events_table + ) + ) as sub_table_2; + +-- Recurring table in the FROM clause of a subquery in the FROM clause +-- Recurring table is created by joining a two recurrign table +SELECT + SUM(user_id) +FROM + (SELECT + * + FROM + (SELECT + user_id + FROM + users_table + ORDER BY + user_id + LIMIT 10) as t1 + INNER JOIN + (SELECT + user_id as user_id_2 + FROM + users_table + ORDER BY + user_id + LIMIT + 10) as t2 + ON + t1.user_id = t2.user_id_2 + WHERE + t1.user_id + IN + (SELECT + value_2 + FROM + events_table) + ) as t3 +WHERE + user_id +>ANY + (SELECT + min(user_id) + FROM + events_table + GROUP BY + user_id); + +-- Same example with the above query, but now check the rows with EXISTS +SELECT + SUM(user_id) +FROM + (SELECT + * + FROM + (SELECT + user_id + FROM + users_table + ORDER BY + user_id + LIMIT 10) as t1 + INNER JOIN + (SELECT + user_id as user_id_2 + FROM + users_table + ORDER BY + user_id + LIMIT + 10) as t2 + ON + t1.user_id = t2.user_id_2 + WHERE + t1.user_id + IN + (SELECT + value_2 + FROM + events_table) + ) as t3 +WHERE EXISTS + (SELECT + 1,2 + FROM + events_table + WHERE + events_table.value_2 = events_table.user_id); + +-- Same query with the above one, yet now we check the row's NON-existence +-- by NOT EXISTS. Note that, max value_2 of events_table is 5 +SELECT + SUM(user_id) +FROM + (SELECT + * + FROM + (SELECT + user_id + FROM + users_table + ORDER BY + user_id + LIMIT 10) as t1 + INNER JOIN + (SELECT + user_id as user_id_2 + FROM + users_table + ORDER BY + user_id + LIMIT + 10) as t2 + ON + t1.user_id = t2.user_id_2 + WHERE + t1.user_id + IN + (SELECT + value_2 + FROM + events_table) + ) as t3 +WHERE NOT EXISTS + (SELECT + 1,2 + FROM + events_table + WHERE + events_table.value_2 = events_table.user_id + 6); + +-- Check the existence of row by comparing it with the result of subquery in +-- WHERE clause. Note that subquery is planned recursively since there is no +-- distributed table in the from +SELECT + * +FROM + (SELECT + user_id, value_1 + FROM + users_table + ORDER BY + user_id ASC, + value_1 ASC + LIMIT 10) as t3 +WHERE row(user_id, value_1) = + (SELECT + min(user_id) + 1, min(user_id) + 1 + FROM + events_table); + +-- Recursively plan subquery in WHERE clause when the FROM clause has a subquery +-- generated by generate_series function +SELECT + * +FROM + (SELECT + * + FROM + generate_series(1,10) + ) as gst +WHERE + generate_series +IN + (SELECT + value_2 + FROM + events_table + ) +ORDER BY + generate_series ASC; + +-- Similar to the test above, now we also have a generate_series in WHERE clause +SELECT + * +FROM + (SELECT + * + FROM + generate_series(1,10) + ) as gst +WHERE + generate_series +IN + (SELECT + user_id + FROM + users_table + WHERE + user_id + IN + (SELECT + * + FROM + generate_series(1,3) + ) + ) +ORDER BY + generate_series ASC; + +-- 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); +INSERT INTO local_table VALUES(1,1), (2,2); + +SELECT + * +FROM + (SELECT + * + FROM + local_table) as sub_table +WHERE + id +IN + (SELECT + user_id + FROM + users_table); + +-- Use local table in WHERE clause +SELECT + COUNT(*) +FROM + (SELECT + * + FROM + users_table + ORDER BY + user_id + LIMIT + 10) as sub_table +WHERE + user_id +IN + (SELECT + id + FROM + local_table); + +DROP TABLE local_table; + +SET client_min_messages TO DEFAULT; + +DROP SCHEMA subquery_in_where CASCADE; +SET search_path TO public; diff --git a/src/test/regress/sql/with_prepare.sql b/src/test/regress/sql/with_prepare.sql index ac26508f1..ed4a72708 100644 --- a/src/test/regress/sql/with_prepare.sql +++ b/src/test/regress/sql/with_prepare.sql @@ -185,6 +185,18 @@ ORDER BY 1, 2, 3, 4, 5, 6 LIMIT 10; +-- Prepare a statement with a sublink in WHERE clause and recurring tuple in FORM +PREPARE prepared_test_6 AS +WITH event_id AS ( + SELECT user_id as events_user_id, time as events_time, event_type + FROM events_table +) +SELECT + count(*) +FROM + event_id +WHERE + events_user_id IN (SELECT user_id FROM users_table); EXECUTE prepared_test_1; @@ -222,6 +234,13 @@ EXECUTE prepared_test_5(4, 5, 6); EXECUTE prepared_test_5(5, 6, 7); EXECUTE prepared_test_5(6, 7, 8); +EXECUTE prepared_test_6; +EXECUTE prepared_test_6; +EXECUTE prepared_test_6; +EXECUTE prepared_test_6; +EXECUTE prepared_test_6; +EXECUTE prepared_test_6; + EXECUTE prepared_partition_column_insert(1); DEALLOCATE ALL;