From f2538a456f075f15e475e87260c99062992dd69d Mon Sep 17 00:00:00 2001 From: Marco Slot Date: Mon, 7 Dec 2020 06:58:23 +0100 Subject: [PATCH] Support co-located/recurring sublinks in the target list --- .../planner/multi_logical_optimizer.c | 11 +- .../planner/multi_logical_planner.c | 12 - .../planner/query_pushdown_planning.c | 185 ++++---- .../distributed/query_pushdown_planning.h | 2 +- src/test/regress/expected/cte_inline.out | 222 +++++---- src/test/regress/expected/cte_inline_0.out | 212 ++++----- .../regress/expected/multi_insert_select.out | 15 +- .../expected/multi_mx_router_planner.out | 3 +- .../regress/expected/multi_router_planner.out | 3 +- .../multi_router_planner_fast_path.out | 3 +- .../regress/expected/multi_simple_queries.out | 3 +- src/test/regress/expected/multi_subquery.out | 16 +- ...lti_subquery_in_where_reference_clause.out | 12 +- .../expected/multi_utility_statements.out | 4 +- .../expected/subquery_in_targetlist.out | 431 ++++++++++++++++++ .../regress/expected/subquery_in_where.out | 3 +- src/test/regress/expected/with_basics.out | 15 +- src/test/regress/multi_schedule | 3 +- src/test/regress/sql/cte_inline.sql | 16 +- src/test/regress/sql/multi_subquery.sql | 4 +- .../regress/sql/subquery_in_targetlist.sql | 294 ++++++++++++ src/test/regress/sql/with_basics.sql | 8 +- 22 files changed, 1072 insertions(+), 405 deletions(-) create mode 100644 src/test/regress/expected/subquery_in_targetlist.out create mode 100644 src/test/regress/sql/subquery_in_targetlist.sql diff --git a/src/backend/distributed/planner/multi_logical_optimizer.c b/src/backend/distributed/planner/multi_logical_optimizer.c index 0753bf0ee..6e36c0f9f 100644 --- a/src/backend/distributed/planner/multi_logical_optimizer.c +++ b/src/backend/distributed/planner/multi_logical_optimizer.c @@ -39,12 +39,12 @@ #include "distributed/multi_logical_planner.h" #include "distributed/multi_physical_planner.h" #include "distributed/pg_dist_partition.h" +#include "distributed/query_pushdown_planning.h" #include "distributed/tdigest_extension.h" #include "distributed/worker_protocol.h" #include "distributed/version_compat.h" #include "nodes/makefuncs.h" #include "nodes/nodeFuncs.h" -#include "nodes/print.h" #include "optimizer/clauses.h" #include "optimizer/tlist.h" #if PG_VERSION_NUM >= PG_VERSION_12 @@ -482,6 +482,15 @@ MultiLogicalPlanOptimize(MultiTreeRoot *multiLogicalPlan) errhint("You might need to disable approximations for either " "count(distinct) or limit through configuration."))); } + + if (TargetListContainsSubquery(masterExtendedOpNode->targetList)) + { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot push down subquery on the target list"), + errdetail("Subqueries in the SELECT part of the query can only " + "be pushed down if they happen before aggregates and " + "window functions"))); + } } diff --git a/src/backend/distributed/planner/multi_logical_planner.c b/src/backend/distributed/planner/multi_logical_planner.c index 1f028ff0e..b74b7a352 100644 --- a/src/backend/distributed/planner/multi_logical_planner.c +++ b/src/backend/distributed/planner/multi_logical_planner.c @@ -833,18 +833,6 @@ DeferErrorIfQueryNotSupported(Query *queryTree) const char *filterHint = "Consider using an equality filter on the distributed " "table's partition column."; - /* - * There could be Sublinks in the target list as well. To produce better - * error messages we're checking if that's the case. - */ - if (queryTree->hasSubLinks && TargetListContainsSubquery(queryTree)) - { - preconditionsSatisfied = false; - errorMessage = "could not run distributed query with subquery outside the " - "FROM, WHERE and HAVING clauses"; - errorHint = filterHint; - } - if (queryTree->setOperations) { preconditionsSatisfied = false; diff --git a/src/backend/distributed/planner/query_pushdown_planning.c b/src/backend/distributed/planner/query_pushdown_planning.c index e2e8be6cd..0cb935a13 100644 --- a/src/backend/distributed/planner/query_pushdown_planning.c +++ b/src/backend/distributed/planner/query_pushdown_planning.c @@ -86,12 +86,9 @@ static bool ContainsRecurringRTE(RangeTblEntry *rangeTableEntry, static bool ContainsRecurringRangeTable(List *rangeTable, RecurringTuplesType *recurType); static bool HasRecurringTuples(Node *node, RecurringTuplesType *recurType); static MultiNode * SubqueryPushdownMultiNodeTree(Query *queryTree); -static void UpdateVarMappingsForExtendedOpNode(List *columnList, - List *subqueryTargetEntryList); -static void UpdateColumnToMatchingTargetEntry(Var *column, - List *targetEntryList); static MultiTable * MultiSubqueryPushdownTable(Query *subquery); -static List * CreateSubqueryTargetEntryList(List *columnList); +static List * CreateSubqueryTargetListAndAdjustVars(List *columnList); +static AttrNumber FindResnoForVarInTargetList(List *targetList, int varno, int varattno); static bool RelationInfoContainsOnlyRecurringTuples(PlannerInfo *plannerInfo, Relids relids); @@ -125,6 +122,16 @@ ShouldUseSubqueryPushDown(Query *originalQuery, Query *rewrittenQuery, return true; } + /* + * We check the existence of subqueries in the SELECT clause on the modified + * query. + */ + if (TargetListContainsSubquery(rewrittenQuery->targetList)) + { + return true; + } + + /* * We check if postgres planned any semi joins, MultiNodeTree doesn't * support these so we fail. Postgres is able to replace some IN/ANY @@ -303,9 +310,9 @@ WhereOrHavingClauseContainsSubquery(Query *query) * any subqueries in the WHERE clause. */ bool -TargetListContainsSubquery(Query *query) +TargetListContainsSubquery(List *targetList) { - return FindNodeMatchingCheckFunction((Node *) query->targetList, IsNodeSubquery); + return FindNodeMatchingCheckFunction((Node *) targetList, IsNodeSubquery); } @@ -662,38 +669,28 @@ DeferErrorIfFromClauseRecurs(Query *queryTree) if (recurType == RECURRING_TUPLES_REFERENCE_TABLE) { return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED, - "cannot pushdown the subquery", - "Reference tables are not allowed in FROM " - "clause when the query has subqueries in " - "WHERE clause and it references a column " - "from another query", NULL); + "correlated subqueries are not supported when " + "the FROM clause contains a reference table", NULL, NULL); } else if (recurType == RECURRING_TUPLES_FUNCTION) { return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED, - "cannot pushdown the subquery", - "Functions are not allowed in FROM " - "clause when the query has subqueries in " - "WHERE clause and it references a column " - "from another query", NULL); + "correlated subqueries are not supported when " + "the FROM clause contains a set returning function", NULL, + NULL); } else if (recurType == RECURRING_TUPLES_RESULT_FUNCTION) { return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED, - "cannot pushdown the subquery", - "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", NULL); + "correlated subqueries are not supported when " + "the FROM clause contains a CTE or subquery", NULL, NULL); } else if (recurType == RECURRING_TUPLES_EMPTY_JOIN_TREE) { return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED, - "cannot pushdown the subquery", - "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", NULL); + "correlated subqueries are not supported when " + "the FROM clause contains a subquery without FROM", NULL, + NULL); } /* @@ -1058,8 +1055,7 @@ DeferErrorIfCannotPushdownSubquery(Query *subqueryTree, bool outerMostQueryHasLi deferredError = DeferErrorIfFromClauseRecurs(subqueryTree); if (deferredError) { - preconditionsSatisfied = false; - errorDetail = (char *) deferredError->detail; + return deferredError; } @@ -1539,18 +1535,12 @@ SubqueryPushdownMultiNodeTree(Query *originalQuery) * columnList. Columns mentioned in multiProject node and multiExtendedOp * node are indexed with their respective position in columnList. */ - List *targetColumnList = pull_var_clause_default((Node *) targetEntryList); + List *targetColumnList = pull_vars_of_level((Node *) targetEntryList, 0); List *havingClauseColumnList = pull_var_clause_default(queryTree->havingQual); List *columnList = list_concat(targetColumnList, havingClauseColumnList); /* create a target entry for each unique column */ - List *subqueryTargetEntryList = CreateSubqueryTargetEntryList(columnList); - - /* - * Update varno/varattno fields of columns in columnList to - * point to corresponding target entry in subquery target entry list. - */ - UpdateVarMappingsForExtendedOpNode(columnList, subqueryTargetEntryList); + List *subqueryTargetEntryList = CreateSubqueryTargetListAndAdjustVars(columnList); /* new query only has target entries, join tree, and rtable*/ Query *pushedDownQuery = makeNode(Query); @@ -1633,33 +1623,55 @@ SubqueryPushdownMultiNodeTree(Query *originalQuery) /* - * CreateSubqueryTargetEntryList creates a target entry for each unique column - * in the column list and returns the target entry list. + * CreateSubqueryTargetListAndAdjustVars creates a target entry for each unique + * column in the column list, adjusts the columns to point into the subquery target + * list and returns the new subquery target list. */ static List * -CreateSubqueryTargetEntryList(List *columnList) +CreateSubqueryTargetListAndAdjustVars(List *columnList) { - AttrNumber resNo = 1; - List *uniqueColumnList = NIL; + Var *column = NULL; List *subqueryTargetEntryList = NIL; - Node *column = NULL; foreach_ptr(column, columnList) { - uniqueColumnList = list_append_unique(uniqueColumnList, column); - } + /* + * To avoid adding the same column multiple times, we first check whether there + * is already a target entry containing a Var with the given varno and varattno. + */ + AttrNumber resNo = FindResnoForVarInTargetList(subqueryTargetEntryList, + column->varno, column->varattno); + if (resNo == InvalidAttrNumber) + { + /* Var is not yet on the target list, create a new entry */ + resNo = list_length(subqueryTargetEntryList) + 1; - foreach_ptr(column, uniqueColumnList) - { - TargetEntry *newTargetEntry = makeNode(TargetEntry); + /* + * The join tree in the subquery is an exact duplicate of the original + * query. Hence, we can make a copy of the original Var. However, if the + * original Var was in a sublink it would be pointing up whereas now it + * will be placed directly on the target list. Hence we reset the + * varlevelsup. + */ + Var *subqueryTargetListVar = (Var *) copyObject(column); - newTargetEntry->expr = (Expr *) copyObject(column); - newTargetEntry->resname = WorkerColumnName(resNo); - newTargetEntry->resjunk = false; - newTargetEntry->resno = resNo; + subqueryTargetListVar->varlevelsup = 0; - subqueryTargetEntryList = lappend(subqueryTargetEntryList, newTargetEntry); - resNo++; + TargetEntry *newTargetEntry = makeNode(TargetEntry); + newTargetEntry->expr = (Expr *) subqueryTargetListVar; + newTargetEntry->resname = WorkerColumnName(resNo); + newTargetEntry->resjunk = false; + newTargetEntry->resno = resNo; + + subqueryTargetEntryList = lappend(subqueryTargetEntryList, newTargetEntry); + } + + /* + * Change the original column reference to point to the target list + * entry in the subquery. There is only 1 subquery, so the varno is 1. + */ + column->varno = 1; + column->varattno = resNo; } return subqueryTargetEntryList; @@ -1667,63 +1679,30 @@ CreateSubqueryTargetEntryList(List *columnList) /* - * UpdateVarMappingsForExtendedOpNode updates varno/varattno fields of columns - * in columnList to point to corresponding target in subquery target entry - * list. + * FindResnoForVarInTargetList finds a Var on a target list that has the given varno + * (range table entry number) and varattno (column number) and returns the resno + * of the target list entry. */ -static void -UpdateVarMappingsForExtendedOpNode(List *columnList, List *subqueryTargetEntryList) +static AttrNumber +FindResnoForVarInTargetList(List *targetList, int varno, int varattno) { - Var *column = NULL; - foreach_ptr(column, columnList) + TargetEntry *targetEntry = NULL; + foreach_ptr(targetEntry, targetList) { - /* - * As an optimization, subqueryTargetEntryList only consists of - * distinct elements. In other words, any duplicate entries in the - * target list consolidated into a single element to prevent pulling - * unnecessary data from the worker nodes (e.g. SELECT a,a,a,b,b,b FROM x; - * is turned into SELECT a,b FROM x_102008). - * - * Thus, at this point we should iterate on the subqueryTargetEntryList - * and ensure that the column on the extended op node points to the - * correct target entry. - */ - UpdateColumnToMatchingTargetEntry(column, subqueryTargetEntryList); - } -} - - -/* - * UpdateColumnToMatchingTargetEntry sets the variable of given column entry to - * the matching entry of the targetEntryList. Since data type of the column can - * be different from the types of the elements of targetEntryList, we use flattenedExpr. - */ -static void -UpdateColumnToMatchingTargetEntry(Var *column, List *targetEntryList) -{ - ListCell *targetEntryCell = NULL; - - foreach(targetEntryCell, targetEntryList) - { - TargetEntry *targetEntry = (TargetEntry *) lfirst(targetEntryCell); - - if (IsA(targetEntry->expr, Var)) + if (!IsA(targetEntry->expr, Var)) { - Var *targetEntryVar = (Var *) targetEntry->expr; - - if (IsA(column, Var) && equal(column, targetEntryVar)) - { - column->varno = 1; - column->varattno = targetEntry->resno; - break; - } + continue; } - else + + Var *targetEntryVar = (Var *) targetEntry->expr; + + if (targetEntryVar->varno == varno && targetEntryVar->varattno == varattno) { - elog(ERROR, "unrecognized node type on the target list: %d", - nodeTag(targetEntry->expr)); + return targetEntry->resno; } } + + return InvalidAttrNumber; } diff --git a/src/include/distributed/query_pushdown_planning.h b/src/include/distributed/query_pushdown_planning.h index 911be8d1e..105660343 100644 --- a/src/include/distributed/query_pushdown_planning.h +++ b/src/include/distributed/query_pushdown_planning.h @@ -29,7 +29,7 @@ extern bool JoinTreeContainsSubquery(Query *query); extern bool IsNodeSubquery(Node *node); extern bool HasEmptyJoinTree(Query *query); extern bool WhereOrHavingClauseContainsSubquery(Query *query); -extern bool TargetListContainsSubquery(Query *query); +extern bool TargetListContainsSubquery(List *targetList); extern bool SafeToPushdownWindowFunction(Query *query, StringInfo *errorDetail); extern MultiNode * SubqueryMultiNodeTree(Query *originalQuery, Query *queryTree, diff --git a/src/test/regress/expected/cte_inline.out b/src/test/regress/expected/cte_inline.out index 8ff3f267c..a1b9ba078 100644 --- a/src/test/regress/expected/cte_inline.out +++ b/src/test/regress/expected/cte_inline.out @@ -23,41 +23,41 @@ SET client_min_messages TO DEBUG; -- plan the query WITH cte_1 AS (SELECT * FROM test_table) SELECT - *, (SELECT 1) + * FROM - cte_1 + test_table LEFT JOIN cte_1 USING (value) ORDER BY 1 DESC LIMIT 3; DEBUG: CTE cte_1 is going to be inlined via distributed planning DEBUG: Router planner cannot handle multi-shard select queries DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: generating subplan XXX_1 for CTE cte_1: SELECT key, value, other_value FROM cte_inline.test_table +DEBUG: generating subplan XXX_1 for subquery SELECT key, value, other_value FROM cte_inline.test_table +DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT test_table.value, test_table.key, test_table.other_value, cte_1.key, cte_1.other_value FROM (cte_inline.test_table LEFT JOIN (SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb)) cte_1 USING (value)) ORDER BY test_table.value DESC LIMIT 3 DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT key, value, other_value, (SELECT 1) FROM (SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb)) cte_1 ORDER BY key DESC LIMIT 3 -DEBUG: Creating router plan - key | value | other_value | ?column? +DEBUG: push down of limit count: 3 + value | key | other_value | key | other_value --------------------------------------------------------------------- - 9 | test9 | {"f1": 9, "f2": 162, "f3": "test9"} | 1 - 9 | test19 | {"f1": 19, "f2": 342, "f3": "test19"} | 1 - 9 | test29 | {"f1": 29, "f2": 522, "f3": "test29"} | 1 + test99 | 9 | {"f1": 99, "f2": 1782, "f3": "test99"} | 9 | {"f1": 99, "f2": 1782, "f3": "test99"} + test98 | 8 | {"f1": 98, "f2": 1764, "f3": "test98"} | 8 | {"f1": 98, "f2": 1764, "f3": "test98"} + test97 | 7 | {"f1": 97, "f2": 1746, "f3": "test97"} | 7 | {"f1": 97, "f2": 1746, "f3": "test97"} (3 rows) -- Should still not be inlined even if NOT MATERIALIZED is passed WITH cte_1 AS NOT MATERIALIZED (SELECT * FROM test_table) SELECT - *, (SELECT 1) + * FROM - cte_1 + test_table LEFT JOIN cte_1 USING (value) ORDER BY 2 DESC LIMIT 1; DEBUG: CTE cte_1 is going to be inlined via distributed planning DEBUG: Router planner cannot handle multi-shard select queries DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: generating subplan XXX_1 for CTE cte_1: SELECT key, value, other_value FROM cte_inline.test_table +DEBUG: generating subplan XXX_1 for subquery SELECT key, value, other_value FROM cte_inline.test_table +DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT test_table.value, test_table.key, test_table.other_value, cte_1.key, cte_1.other_value FROM (cte_inline.test_table LEFT JOIN (SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb)) cte_1 USING (value)) ORDER BY test_table.key DESC LIMIT 1 DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT key, value, other_value, (SELECT 1) FROM (SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb)) cte_1 ORDER BY value DESC LIMIT 1 -DEBUG: Creating router plan - key | value | other_value | ?column? +DEBUG: push down of limit count: 1 + value | key | other_value | key | other_value --------------------------------------------------------------------- - 9 | test99 | {"f1": 99, "f2": 1782, "f3": "test99"} | 1 + test9 | 9 | {"f1": 9, "f2": 162, "f3": "test9"} | 9 | {"f1": 9, "f2": 162, "f3": "test9"} (1 row) -- the cte can be inlined because the unsupported @@ -125,11 +125,7 @@ FROM ORDER BY 2 DESC LIMIT 1; DEBUG: CTE cte_1 is going to be inlined via distributed planning DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: generating subplan XXX_1 for CTE cte_1: SELECT key, value, other_value FROM cte_inline.test_table -DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT key, value, other_value, (SELECT 1) FROM (SELECT cte_1.key, cte_1.value, cte_1.other_value FROM (SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb)) cte_1) foo ORDER BY value DESC LIMIT 1 -DEBUG: Creating router plan +DEBUG: push down of limit count: 1 key | value | other_value | ?column? --------------------------------------------------------------------- 9 | test99 | {"f1": 99, "f2": 1782, "f3": "test99"} | 1 @@ -153,15 +149,9 @@ DEBUG: CTE top_cte is going to be inlined via distributed planning DEBUG: CTE cte_1 is going to be inlined via distributed planning DEBUG: Router planner cannot handle multi-shard select queries DEBUG: Router planner cannot handle multi-shard select queries +DEBUG: generating subplan XXX_1 for subquery SELECT key, value, other_value, (SELECT 1) FROM (SELECT cte_1.key, cte_1.value, cte_1.other_value FROM (SELECT test_table.key, test_table.value, test_table.other_value FROM cte_inline.test_table) cte_1) foo +DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT count(*) AS count FROM (SELECT test_table.key, test_table.value, test_table.other_value FROM cte_inline.test_table) top_cte, (SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value, intermediate_result."?column?" FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb, "?column?" integer)) bar(key, value, other_value, "?column?") DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: generating subplan XXX_1 for CTE top_cte: SELECT key, value, other_value FROM cte_inline.test_table -DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: generating subplan XXX_2 for CTE cte_1: SELECT key, value, other_value FROM cte_inline.test_table -DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: Creating router plan -DEBUG: generating subplan XXX_3 for subquery SELECT key, value, other_value, (SELECT 1) FROM (SELECT cte_1.key, cte_1.value, cte_1.other_value FROM (SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value FROM read_intermediate_result('XXX_2'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb)) cte_1) foo -DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT count(*) AS count FROM (SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb)) top_cte, (SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value, intermediate_result."?column?" FROM read_intermediate_result('XXX_3'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb, "?column?" integer)) bar(key, value, other_value, "?column?") -DEBUG: Creating router plan count --------------------------------------------------------------------- 10201 @@ -187,12 +177,8 @@ WHERE KEY IN DEBUG: CTE cte_1 is going to be inlined via distributed planning DEBUG: Router planner cannot handle multi-shard select queries DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: generating subplan XXX_1 for CTE cte_1: SELECT key, value, other_value FROM cte_inline.test_table -DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: Creating router plan -DEBUG: generating subplan XXX_2 for subquery SELECT (SELECT 1) FROM (SELECT foo.key, foo.value, foo.other_value, random() AS random FROM (SELECT cte_1.key, cte_1.value, cte_1.other_value FROM (SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb)) cte_1) foo) bar -DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT count(*) AS count FROM cte_inline.test_table WHERE (key OPERATOR(pg_catalog.=) ANY (SELECT intermediate_result."?column?" FROM read_intermediate_result('XXX_2'::text, 'binary'::citus_copy_format) intermediate_result("?column?" integer))) +DEBUG: generating subplan XXX_1 for subquery SELECT (SELECT 1) FROM (SELECT foo.key, foo.value, foo.other_value, random() AS random FROM (SELECT cte_1.key, cte_1.value, cte_1.other_value FROM (SELECT test_table.key, test_table.value, test_table.other_value FROM cte_inline.test_table) cte_1) foo) bar +DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT count(*) AS count FROM cte_inline.test_table WHERE (key OPERATOR(pg_catalog.=) ANY (SELECT intermediate_result."?column?" FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result("?column?" integer))) DEBUG: Router planner cannot handle multi-shard select queries count --------------------------------------------------------------------- @@ -734,17 +720,10 @@ DEBUG: Router planner cannot handle multi-shard select queries DEBUG: push down of limit count: 3 DEBUG: generating subplan XXX_1 for subquery SELECT key, value, other_value FROM cte_inline.test_table ORDER BY key DESC LIMIT 3 DEBUG: Router planner cannot handle multi-shard select queries +DEBUG: generating subplan XXX_2 for subquery SELECT key, value, other_value, (SELECT 1) FROM (SELECT test_table.key, test_table.value, test_table.other_value FROM cte_inline.test_table) cte_1 DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: generating subplan XXX_1 for CTE cte_1: SELECT key, value, other_value FROM cte_inline.test_table -DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: generating subplan XXX_2 for CTE cte_2: SELECT key, value, other_value FROM cte_inline.test_table ORDER BY key DESC LIMIT 3 -DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: push down of limit count: 3 -DEBUG: Creating router plan -DEBUG: generating subplan XXX_3 for subquery SELECT key, value, other_value, (SELECT 1) FROM (SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb)) cte_1 -DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: generating subplan XXX_4 for subquery SELECT key, value, other_value, 1 FROM cte_inline.test_table -DEBUG: Plan XXX query after replacing subqueries and CTEs: (SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value, intermediate_result."?column?" FROM read_intermediate_result('XXX_3'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb, "?column?" integer) EXCEPT SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value, intermediate_result."?column?" FROM read_intermediate_result('XXX_4'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb, "?column?" integer)) UNION SELECT cte_2.key, cte_2.value, cte_2.other_value, 1 FROM (SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value FROM read_intermediate_result('XXX_2'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb)) cte_2 ORDER BY 1, 2 +DEBUG: generating subplan XXX_3 for subquery SELECT key, value, other_value, 1 FROM cte_inline.test_table +DEBUG: Plan XXX query after replacing subqueries and CTEs: (SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value, intermediate_result."?column?" FROM read_intermediate_result('XXX_2'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb, "?column?" integer) EXCEPT SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value, intermediate_result."?column?" FROM read_intermediate_result('XXX_3'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb, "?column?" integer)) UNION SELECT cte_2.key, cte_2.value, cte_2.other_value, 1 FROM (SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb)) cte_2 ORDER BY 1, 2 DEBUG: Creating router plan key | value | other_value | ?column? --------------------------------------------------------------------- @@ -772,8 +751,11 @@ DEBUG: Router planner cannot handle multi-shard select queries DEBUG: generating subplan XXX_2 for CTE cte_2: SELECT key, value, other_value FROM cte_inline.test_table DEBUG: Router planner cannot handle multi-shard select queries DEBUG: Router planner cannot handle multi-shard select queries -ERROR: could not run distributed query with subquery outside the FROM, WHERE and HAVING clauses -HINT: Consider using an equality filter on the distributed table's partition column. +DEBUG: generating subplan XXX_3 for subquery SELECT key, value, other_value, (SELECT cte_1.key FROM (SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb)) cte_1) AS key FROM cte_inline.test_table +DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value, intermediate_result.key_1 AS key FROM read_intermediate_result('XXX_3'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb, key_1 integer) UNION SELECT cte_2.key, cte_2.value, cte_2.other_value, 1 FROM (SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value FROM read_intermediate_result('XXX_2'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb)) cte_2 +DEBUG: Creating router plan +ERROR: more than one row returned by a subquery used as an expression +CONTEXT: while executing command on localhost:xxxxx -- after inlining CTEs, the query becomes -- subquery pushdown with set operations WITH cte_1 AS (SELECT * FROM test_table), @@ -1002,9 +984,9 @@ PREPARE inlined_cte_without_params AS PREPARE non_inlined_cte_without_params AS WITH cte_1 AS (SELECT * FROM test_table) SELECT - *, (SELECT 1) + * FROM - cte_1 ORDER BY 1 DESC, 2 DESC, 3 DESC LIMIT 3; + test_table LEFT JOIN cte_1 USING (value) ORDER BY 1 DESC, 2 DESC, 3 DESC LIMIT 3; PREPARE inlined_cte_has_parameter_on_non_dist_key(text) AS WITH cte_1 AS (SELECT count(*) FROM test_table WHERE value = $1 GROUP BY key) SELECT * FROM cte_1 ORDER BY 1 DESC LIMIT 3; @@ -1014,9 +996,9 @@ PREPARE inlined_cte_has_parameter_on_dist_key(int) AS PREPARE non_inlined_cte_has_parameter_on_dist_key(int) AS WITH cte_1 AS (SELECT * FROM test_table where key > $1) SELECT - *, (SELECT 1) + * FROM - cte_1 ORDER BY 1 DESC, 2 DESC, 3 DESC LIMIT 3; + test_table LEFT JOIN cte_1 USING (value) ORDER BY 1 DESC, 2 DESC, 3 DESC LIMIT 3; PREPARE retry_planning(int) AS WITH cte_1 AS (SELECT * FROM test_table WHERE key > $1) SELECT json_object_agg(DISTINCT key, value) FROM cte_1 ORDER BY max(key), min(value) DESC LIMIT 3; @@ -1075,55 +1057,55 @@ EXECUTE non_inlined_cte_without_params; DEBUG: CTE cte_1 is going to be inlined via distributed planning DEBUG: Router planner cannot handle multi-shard select queries DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: generating subplan XXX_1 for CTE cte_1: SELECT key, value, other_value FROM cte_inline.test_table +DEBUG: generating subplan XXX_1 for subquery SELECT key, value, other_value FROM cte_inline.test_table +DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT test_table.value, test_table.key, test_table.other_value, cte_1.key, cte_1.other_value FROM (cte_inline.test_table LEFT JOIN (SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb)) cte_1 USING (value)) ORDER BY test_table.value DESC, test_table.key DESC, test_table.other_value DESC LIMIT 3 DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT key, value, other_value, (SELECT 1) FROM (SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb)) cte_1 ORDER BY key DESC, value DESC, other_value DESC LIMIT 3 -DEBUG: Creating router plan - key | value | other_value | ?column? +DEBUG: push down of limit count: 3 + value | key | other_value | key | other_value --------------------------------------------------------------------- - 8 | test98 | | 1 - 8 | test98 | | 1 - 8 | test98 | | 1 + test98 | 8 | | 8 | + test98 | 8 | | 8 | + test98 | 8 | | 8 | (3 rows) EXECUTE non_inlined_cte_without_params; - key | value | other_value | ?column? + value | key | other_value | key | other_value --------------------------------------------------------------------- - 8 | test98 | | 1 - 8 | test98 | | 1 - 8 | test98 | | 1 + test98 | 8 | | 8 | + test98 | 8 | | 8 | + test98 | 8 | | 8 | (3 rows) EXECUTE non_inlined_cte_without_params; - key | value | other_value | ?column? + value | key | other_value | key | other_value --------------------------------------------------------------------- - 8 | test98 | | 1 - 8 | test98 | | 1 - 8 | test98 | | 1 + test98 | 8 | | 8 | + test98 | 8 | | 8 | + test98 | 8 | | 8 | (3 rows) EXECUTE non_inlined_cte_without_params; - key | value | other_value | ?column? + value | key | other_value | key | other_value --------------------------------------------------------------------- - 8 | test98 | | 1 - 8 | test98 | | 1 - 8 | test98 | | 1 + test98 | 8 | | 8 | + test98 | 8 | | 8 | + test98 | 8 | | 8 | (3 rows) EXECUTE non_inlined_cte_without_params; - key | value | other_value | ?column? + value | key | other_value | key | other_value --------------------------------------------------------------------- - 8 | test98 | | 1 - 8 | test98 | | 1 - 8 | test98 | | 1 + test98 | 8 | | 8 | + test98 | 8 | | 8 | + test98 | 8 | | 8 | (3 rows) EXECUTE non_inlined_cte_without_params; - key | value | other_value | ?column? + value | key | other_value | key | other_value --------------------------------------------------------------------- - 8 | test98 | | 1 - 8 | test98 | | 1 - 8 | test98 | | 1 + test98 | 8 | | 8 | + test98 | 8 | | 8 | + test98 | 8 | | 8 | (3 rows) EXECUTE inlined_cte_has_parameter_on_non_dist_key('test1'); @@ -1243,75 +1225,75 @@ EXECUTE non_inlined_cte_has_parameter_on_dist_key(1); DEBUG: CTE cte_1 is going to be inlined via distributed planning DEBUG: Router planner cannot handle multi-shard select queries DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: generating subplan XXX_1 for CTE cte_1: SELECT key, value, other_value FROM cte_inline.test_table WHERE (key OPERATOR(pg_catalog.>) 1) +DEBUG: generating subplan XXX_1 for subquery SELECT key, value, other_value FROM cte_inline.test_table WHERE (key OPERATOR(pg_catalog.>) 1) +DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT test_table.value, test_table.key, test_table.other_value, cte_1.key, cte_1.other_value FROM (cte_inline.test_table LEFT JOIN (SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb)) cte_1 USING (value)) ORDER BY test_table.value DESC, test_table.key DESC, test_table.other_value DESC LIMIT 3 DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT key, value, other_value, (SELECT 1) FROM (SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb)) cte_1 ORDER BY key DESC, value DESC, other_value DESC LIMIT 3 -DEBUG: Creating router plan - key | value | other_value | ?column? +DEBUG: push down of limit count: 3 + value | key | other_value | key | other_value --------------------------------------------------------------------- - 8 | test98 | | 1 - 8 | test98 | | 1 - 8 | test98 | | 1 + test98 | 8 | | 8 | + test98 | 8 | | 8 | + test98 | 8 | | 8 | (3 rows) EXECUTE non_inlined_cte_has_parameter_on_dist_key(2); DEBUG: CTE cte_1 is going to be inlined via distributed planning DEBUG: Router planner cannot handle multi-shard select queries DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: generating subplan XXX_1 for CTE cte_1: SELECT key, value, other_value FROM cte_inline.test_table WHERE (key OPERATOR(pg_catalog.>) 2) +DEBUG: generating subplan XXX_1 for subquery SELECT key, value, other_value FROM cte_inline.test_table WHERE (key OPERATOR(pg_catalog.>) 2) +DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT test_table.value, test_table.key, test_table.other_value, cte_1.key, cte_1.other_value FROM (cte_inline.test_table LEFT JOIN (SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb)) cte_1 USING (value)) ORDER BY test_table.value DESC, test_table.key DESC, test_table.other_value DESC LIMIT 3 DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT key, value, other_value, (SELECT 1) FROM (SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb)) cte_1 ORDER BY key DESC, value DESC, other_value DESC LIMIT 3 -DEBUG: Creating router plan - key | value | other_value | ?column? +DEBUG: push down of limit count: 3 + value | key | other_value | key | other_value --------------------------------------------------------------------- - 8 | test98 | | 1 - 8 | test98 | | 1 - 8 | test98 | | 1 + test98 | 8 | | 8 | + test98 | 8 | | 8 | + test98 | 8 | | 8 | (3 rows) EXECUTE non_inlined_cte_has_parameter_on_dist_key(3); DEBUG: CTE cte_1 is going to be inlined via distributed planning DEBUG: Router planner cannot handle multi-shard select queries DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: generating subplan XXX_1 for CTE cte_1: SELECT key, value, other_value FROM cte_inline.test_table WHERE (key OPERATOR(pg_catalog.>) 3) +DEBUG: generating subplan XXX_1 for subquery SELECT key, value, other_value FROM cte_inline.test_table WHERE (key OPERATOR(pg_catalog.>) 3) +DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT test_table.value, test_table.key, test_table.other_value, cte_1.key, cte_1.other_value FROM (cte_inline.test_table LEFT JOIN (SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb)) cte_1 USING (value)) ORDER BY test_table.value DESC, test_table.key DESC, test_table.other_value DESC LIMIT 3 DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT key, value, other_value, (SELECT 1) FROM (SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb)) cte_1 ORDER BY key DESC, value DESC, other_value DESC LIMIT 3 -DEBUG: Creating router plan - key | value | other_value | ?column? +DEBUG: push down of limit count: 3 + value | key | other_value | key | other_value --------------------------------------------------------------------- - 8 | test98 | | 1 - 8 | test98 | | 1 - 8 | test98 | | 1 + test98 | 8 | | 8 | + test98 | 8 | | 8 | + test98 | 8 | | 8 | (3 rows) EXECUTE non_inlined_cte_has_parameter_on_dist_key(4); DEBUG: CTE cte_1 is going to be inlined via distributed planning DEBUG: Router planner cannot handle multi-shard select queries DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: generating subplan XXX_1 for CTE cte_1: SELECT key, value, other_value FROM cte_inline.test_table WHERE (key OPERATOR(pg_catalog.>) 4) +DEBUG: generating subplan XXX_1 for subquery SELECT key, value, other_value FROM cte_inline.test_table WHERE (key OPERATOR(pg_catalog.>) 4) +DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT test_table.value, test_table.key, test_table.other_value, cte_1.key, cte_1.other_value FROM (cte_inline.test_table LEFT JOIN (SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb)) cte_1 USING (value)) ORDER BY test_table.value DESC, test_table.key DESC, test_table.other_value DESC LIMIT 3 DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT key, value, other_value, (SELECT 1) FROM (SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb)) cte_1 ORDER BY key DESC, value DESC, other_value DESC LIMIT 3 -DEBUG: Creating router plan - key | value | other_value | ?column? +DEBUG: push down of limit count: 3 + value | key | other_value | key | other_value --------------------------------------------------------------------- - 8 | test98 | | 1 - 8 | test98 | | 1 - 8 | test98 | | 1 + test98 | 8 | | 8 | + test98 | 8 | | 8 | + test98 | 8 | | 8 | (3 rows) EXECUTE non_inlined_cte_has_parameter_on_dist_key(5); DEBUG: CTE cte_1 is going to be inlined via distributed planning DEBUG: Router planner cannot handle multi-shard select queries DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: generating subplan XXX_1 for CTE cte_1: SELECT key, value, other_value FROM cte_inline.test_table WHERE (key OPERATOR(pg_catalog.>) 5) +DEBUG: generating subplan XXX_1 for subquery SELECT key, value, other_value FROM cte_inline.test_table WHERE (key OPERATOR(pg_catalog.>) 5) +DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT test_table.value, test_table.key, test_table.other_value, cte_1.key, cte_1.other_value FROM (cte_inline.test_table LEFT JOIN (SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb)) cte_1 USING (value)) ORDER BY test_table.value DESC, test_table.key DESC, test_table.other_value DESC LIMIT 3 DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT key, value, other_value, (SELECT 1) FROM (SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb)) cte_1 ORDER BY key DESC, value DESC, other_value DESC LIMIT 3 -DEBUG: Creating router plan - key | value | other_value | ?column? +DEBUG: push down of limit count: 3 + value | key | other_value | key | other_value --------------------------------------------------------------------- - 8 | test98 | | 1 - 8 | test98 | | 1 - 8 | test98 | | 1 + test98 | 8 | | 8 | + test98 | 8 | | 8 | + test98 | 8 | | 8 | (3 rows) EXECUTE non_inlined_cte_has_parameter_on_dist_key(6); @@ -1320,15 +1302,15 @@ DEBUG: Router planner cannot handle multi-shard select queries DEBUG: CTE cte_1 is going to be inlined via distributed planning DEBUG: Router planner cannot handle multi-shard select queries DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: generating subplan XXX_1 for CTE cte_1: SELECT key, value, other_value FROM cte_inline.test_table WHERE (key OPERATOR(pg_catalog.>) 6) +DEBUG: generating subplan XXX_1 for subquery SELECT key, value, other_value FROM cte_inline.test_table WHERE (key OPERATOR(pg_catalog.>) 6) +DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT test_table.value, test_table.key, test_table.other_value, cte_1.key, cte_1.other_value FROM (cte_inline.test_table LEFT JOIN (SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb)) cte_1 USING (value)) ORDER BY test_table.value DESC, test_table.key DESC, test_table.other_value DESC LIMIT 3 DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT key, value, other_value, (SELECT 1) FROM (SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb)) cte_1 ORDER BY key DESC, value DESC, other_value DESC LIMIT 3 -DEBUG: Creating router plan - key | value | other_value | ?column? +DEBUG: push down of limit count: 3 + value | key | other_value | key | other_value --------------------------------------------------------------------- - 8 | test98 | | 1 - 8 | test98 | | 1 - 8 | test98 | | 1 + test98 | 8 | | 8 | + test98 | 8 | | 8 | + test98 | 8 | | 8 | (3 rows) EXECUTE retry_planning(1); diff --git a/src/test/regress/expected/cte_inline_0.out b/src/test/regress/expected/cte_inline_0.out index 8ed57fc68..7338e4ffe 100644 --- a/src/test/regress/expected/cte_inline_0.out +++ b/src/test/regress/expected/cte_inline_0.out @@ -23,30 +23,30 @@ SET client_min_messages TO DEBUG; -- plan the query WITH cte_1 AS (SELECT * FROM test_table) SELECT - *, (SELECT 1) + * FROM - cte_1 + test_table LEFT JOIN cte_1 USING (value) ORDER BY 1 DESC LIMIT 3; DEBUG: CTE cte_1 is going to be inlined via distributed planning DEBUG: Router planner cannot handle multi-shard select queries DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: generating subplan XXX_1 for CTE cte_1: SELECT key, value, other_value FROM cte_inline.test_table +DEBUG: generating subplan XXX_1 for subquery SELECT key, value, other_value FROM cte_inline.test_table +DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT test_table.value, test_table.key, test_table.other_value, cte_1.key, cte_1.other_value FROM (cte_inline.test_table LEFT JOIN (SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb)) cte_1 USING (value)) ORDER BY test_table.value DESC LIMIT 3 DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT key, value, other_value, (SELECT 1) FROM (SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb)) cte_1 ORDER BY key DESC LIMIT 3 -DEBUG: Creating router plan - key | value | other_value | ?column? +DEBUG: push down of limit count: 3 + value | key | other_value | key | other_value --------------------------------------------------------------------- - 9 | test9 | {"f1": 9, "f2": 162, "f3": "test9"} | 1 - 9 | test19 | {"f1": 19, "f2": 342, "f3": "test19"} | 1 - 9 | test29 | {"f1": 29, "f2": 522, "f3": "test29"} | 1 + test99 | 9 | {"f1": 99, "f2": 1782, "f3": "test99"} | 9 | {"f1": 99, "f2": 1782, "f3": "test99"} + test98 | 8 | {"f1": 98, "f2": 1764, "f3": "test98"} | 8 | {"f1": 98, "f2": 1764, "f3": "test98"} + test97 | 7 | {"f1": 97, "f2": 1746, "f3": "test97"} | 7 | {"f1": 97, "f2": 1746, "f3": "test97"} (3 rows) -- Should still not be inlined even if NOT MATERIALIZED is passed WITH cte_1 AS NOT MATERIALIZED (SELECT * FROM test_table) SELECT - *, (SELECT 1) + * FROM - cte_1 + test_table LEFT JOIN cte_1 USING (value) ORDER BY 2 DESC LIMIT 1; ERROR: syntax error at or near "NOT" -- the cte can be inlined because the unsupported @@ -114,11 +114,7 @@ FROM ORDER BY 2 DESC LIMIT 1; DEBUG: CTE cte_1 is going to be inlined via distributed planning DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: generating subplan XXX_1 for CTE cte_1: SELECT key, value, other_value FROM cte_inline.test_table -DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT key, value, other_value, (SELECT 1) FROM (SELECT cte_1.key, cte_1.value, cte_1.other_value FROM (SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb)) cte_1) foo ORDER BY value DESC LIMIT 1 -DEBUG: Creating router plan +DEBUG: push down of limit count: 1 key | value | other_value | ?column? --------------------------------------------------------------------- 9 | test99 | {"f1": 99, "f2": 1782, "f3": "test99"} | 1 @@ -142,15 +138,9 @@ DEBUG: CTE top_cte is going to be inlined via distributed planning DEBUG: CTE cte_1 is going to be inlined via distributed planning DEBUG: Router planner cannot handle multi-shard select queries DEBUG: Router planner cannot handle multi-shard select queries +DEBUG: generating subplan XXX_1 for subquery SELECT key, value, other_value, (SELECT 1) FROM (SELECT cte_1.key, cte_1.value, cte_1.other_value FROM (SELECT test_table.key, test_table.value, test_table.other_value FROM cte_inline.test_table) cte_1) foo +DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT count(*) AS count FROM (SELECT test_table.key, test_table.value, test_table.other_value FROM cte_inline.test_table) top_cte, (SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value, intermediate_result."?column?" FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb, "?column?" integer)) bar(key, value, other_value, "?column?") DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: generating subplan XXX_1 for CTE top_cte: SELECT key, value, other_value FROM cte_inline.test_table -DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: generating subplan XXX_2 for CTE cte_1: SELECT key, value, other_value FROM cte_inline.test_table -DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: Creating router plan -DEBUG: generating subplan XXX_3 for subquery SELECT key, value, other_value, (SELECT 1) FROM (SELECT cte_1.key, cte_1.value, cte_1.other_value FROM (SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value FROM read_intermediate_result('XXX_2'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb)) cte_1) foo -DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT count(*) AS count FROM (SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb)) top_cte, (SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value, intermediate_result."?column?" FROM read_intermediate_result('XXX_3'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb, "?column?" integer)) bar(key, value, other_value, "?column?") -DEBUG: Creating router plan count --------------------------------------------------------------------- 10201 @@ -176,12 +166,8 @@ WHERE KEY IN DEBUG: CTE cte_1 is going to be inlined via distributed planning DEBUG: Router planner cannot handle multi-shard select queries DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: generating subplan XXX_1 for CTE cte_1: SELECT key, value, other_value FROM cte_inline.test_table -DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: Creating router plan -DEBUG: generating subplan XXX_2 for subquery SELECT (SELECT 1) FROM (SELECT foo.key, foo.value, foo.other_value, random() AS random FROM (SELECT cte_1.key, cte_1.value, cte_1.other_value FROM (SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb)) cte_1) foo) bar -DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT count(*) AS count FROM cte_inline.test_table WHERE (key OPERATOR(pg_catalog.=) ANY (SELECT intermediate_result."?column?" FROM read_intermediate_result('XXX_2'::text, 'binary'::citus_copy_format) intermediate_result("?column?" integer))) +DEBUG: generating subplan XXX_1 for subquery SELECT (SELECT 1) FROM (SELECT foo.key, foo.value, foo.other_value, random() AS random FROM (SELECT cte_1.key, cte_1.value, cte_1.other_value FROM (SELECT test_table.key, test_table.value, test_table.other_value FROM cte_inline.test_table) cte_1) foo) bar +DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT count(*) AS count FROM cte_inline.test_table WHERE (key OPERATOR(pg_catalog.=) ANY (SELECT intermediate_result."?column?" FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result("?column?" integer))) DEBUG: Router planner cannot handle multi-shard select queries count --------------------------------------------------------------------- @@ -626,17 +612,10 @@ DEBUG: Router planner cannot handle multi-shard select queries DEBUG: push down of limit count: 3 DEBUG: generating subplan XXX_1 for subquery SELECT key, value, other_value FROM cte_inline.test_table ORDER BY key DESC LIMIT 3 DEBUG: Router planner cannot handle multi-shard select queries +DEBUG: generating subplan XXX_2 for subquery SELECT key, value, other_value, (SELECT 1) FROM (SELECT test_table.key, test_table.value, test_table.other_value FROM cte_inline.test_table) cte_1 DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: generating subplan XXX_1 for CTE cte_1: SELECT key, value, other_value FROM cte_inline.test_table -DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: generating subplan XXX_2 for CTE cte_2: SELECT key, value, other_value FROM cte_inline.test_table ORDER BY key DESC LIMIT 3 -DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: push down of limit count: 3 -DEBUG: Creating router plan -DEBUG: generating subplan XXX_3 for subquery SELECT key, value, other_value, (SELECT 1) FROM (SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb)) cte_1 -DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: generating subplan XXX_4 for subquery SELECT key, value, other_value, 1 FROM cte_inline.test_table -DEBUG: Plan XXX query after replacing subqueries and CTEs: (SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value, intermediate_result."?column?" FROM read_intermediate_result('XXX_3'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb, "?column?" integer) EXCEPT SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value, intermediate_result."?column?" FROM read_intermediate_result('XXX_4'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb, "?column?" integer)) UNION SELECT cte_2.key, cte_2.value, cte_2.other_value, 1 FROM (SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value FROM read_intermediate_result('XXX_2'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb)) cte_2 ORDER BY 1, 2 +DEBUG: generating subplan XXX_3 for subquery SELECT key, value, other_value, 1 FROM cte_inline.test_table +DEBUG: Plan XXX query after replacing subqueries and CTEs: (SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value, intermediate_result."?column?" FROM read_intermediate_result('XXX_2'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb, "?column?" integer) EXCEPT SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value, intermediate_result."?column?" FROM read_intermediate_result('XXX_3'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb, "?column?" integer)) UNION SELECT cte_2.key, cte_2.value, cte_2.other_value, 1 FROM (SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb)) cte_2 ORDER BY 1, 2 DEBUG: Creating router plan key | value | other_value | ?column? --------------------------------------------------------------------- @@ -664,8 +643,11 @@ DEBUG: Router planner cannot handle multi-shard select queries DEBUG: generating subplan XXX_2 for CTE cte_2: SELECT key, value, other_value FROM cte_inline.test_table DEBUG: Router planner cannot handle multi-shard select queries DEBUG: Router planner cannot handle multi-shard select queries -ERROR: could not run distributed query with subquery outside the FROM, WHERE and HAVING clauses -HINT: Consider using an equality filter on the distributed table's partition column. +DEBUG: generating subplan XXX_3 for subquery SELECT key, value, other_value, (SELECT cte_1.key FROM (SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb)) cte_1) AS key FROM cte_inline.test_table +DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value, intermediate_result.key_1 AS key FROM read_intermediate_result('XXX_3'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb, key_1 integer) UNION SELECT cte_2.key, cte_2.value, cte_2.other_value, 1 FROM (SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value FROM read_intermediate_result('XXX_2'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb)) cte_2 +DEBUG: Creating router plan +ERROR: more than one row returned by a subquery used as an expression +CONTEXT: while executing command on localhost:xxxxx -- after inlining CTEs, the query becomes -- subquery pushdown with set operations WITH cte_1 AS (SELECT * FROM test_table), @@ -881,9 +863,9 @@ PREPARE inlined_cte_without_params AS PREPARE non_inlined_cte_without_params AS WITH cte_1 AS (SELECT * FROM test_table) SELECT - *, (SELECT 1) + * FROM - cte_1 ORDER BY 1 DESC, 2 DESC, 3 DESC LIMIT 3; + test_table LEFT JOIN cte_1 USING (value) ORDER BY 1 DESC, 2 DESC, 3 DESC LIMIT 3; PREPARE inlined_cte_has_parameter_on_non_dist_key(text) AS WITH cte_1 AS (SELECT count(*) FROM test_table WHERE value = $1 GROUP BY key) SELECT * FROM cte_1 ORDER BY 1 DESC LIMIT 3; @@ -893,9 +875,9 @@ PREPARE inlined_cte_has_parameter_on_dist_key(int) AS PREPARE non_inlined_cte_has_parameter_on_dist_key(int) AS WITH cte_1 AS (SELECT * FROM test_table where key > $1) SELECT - *, (SELECT 1) + * FROM - cte_1 ORDER BY 1 DESC, 2 DESC, 3 DESC LIMIT 3; + test_table LEFT JOIN cte_1 USING (value) ORDER BY 1 DESC, 2 DESC, 3 DESC LIMIT 3; PREPARE retry_planning(int) AS WITH cte_1 AS (SELECT * FROM test_table WHERE key > $1) SELECT json_object_agg(DISTINCT key, value) FROM cte_1 ORDER BY max(key), min(value) DESC LIMIT 3; @@ -954,55 +936,55 @@ EXECUTE non_inlined_cte_without_params; DEBUG: CTE cte_1 is going to be inlined via distributed planning DEBUG: Router planner cannot handle multi-shard select queries DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: generating subplan XXX_1 for CTE cte_1: SELECT key, value, other_value FROM cte_inline.test_table +DEBUG: generating subplan XXX_1 for subquery SELECT key, value, other_value FROM cte_inline.test_table +DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT test_table.value, test_table.key, test_table.other_value, cte_1.key, cte_1.other_value FROM (cte_inline.test_table LEFT JOIN (SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb)) cte_1 USING (value)) ORDER BY test_table.value DESC, test_table.key DESC, test_table.other_value DESC LIMIT 3 DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT key, value, other_value, (SELECT 1) FROM (SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb)) cte_1 ORDER BY key DESC, value DESC, other_value DESC LIMIT 3 -DEBUG: Creating router plan - key | value | other_value | ?column? +DEBUG: push down of limit count: 3 + value | key | other_value | key | other_value --------------------------------------------------------------------- - 9 | test99 | | 1 - 9 | test99 | | 1 - 9 | test99 | | 1 + test99 | 9 | | 9 | + test99 | 9 | | 9 | + test99 | 9 | | 9 | (3 rows) EXECUTE non_inlined_cte_without_params; - key | value | other_value | ?column? + value | key | other_value | key | other_value --------------------------------------------------------------------- - 9 | test99 | | 1 - 9 | test99 | | 1 - 9 | test99 | | 1 + test99 | 9 | | 9 | + test99 | 9 | | 9 | + test99 | 9 | | 9 | (3 rows) EXECUTE non_inlined_cte_without_params; - key | value | other_value | ?column? + value | key | other_value | key | other_value --------------------------------------------------------------------- - 9 | test99 | | 1 - 9 | test99 | | 1 - 9 | test99 | | 1 + test99 | 9 | | 9 | + test99 | 9 | | 9 | + test99 | 9 | | 9 | (3 rows) EXECUTE non_inlined_cte_without_params; - key | value | other_value | ?column? + value | key | other_value | key | other_value --------------------------------------------------------------------- - 9 | test99 | | 1 - 9 | test99 | | 1 - 9 | test99 | | 1 + test99 | 9 | | 9 | + test99 | 9 | | 9 | + test99 | 9 | | 9 | (3 rows) EXECUTE non_inlined_cte_without_params; - key | value | other_value | ?column? + value | key | other_value | key | other_value --------------------------------------------------------------------- - 9 | test99 | | 1 - 9 | test99 | | 1 - 9 | test99 | | 1 + test99 | 9 | | 9 | + test99 | 9 | | 9 | + test99 | 9 | | 9 | (3 rows) EXECUTE non_inlined_cte_without_params; - key | value | other_value | ?column? + value | key | other_value | key | other_value --------------------------------------------------------------------- - 9 | test99 | | 1 - 9 | test99 | | 1 - 9 | test99 | | 1 + test99 | 9 | | 9 | + test99 | 9 | | 9 | + test99 | 9 | | 9 | (3 rows) EXECUTE inlined_cte_has_parameter_on_non_dist_key('test1'); @@ -1130,75 +1112,75 @@ EXECUTE non_inlined_cte_has_parameter_on_dist_key(1); DEBUG: CTE cte_1 is going to be inlined via distributed planning DEBUG: Router planner cannot handle multi-shard select queries DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: generating subplan XXX_1 for CTE cte_1: SELECT key, value, other_value FROM cte_inline.test_table WHERE (key OPERATOR(pg_catalog.>) 1) +DEBUG: generating subplan XXX_1 for subquery SELECT key, value, other_value FROM cte_inline.test_table WHERE (key OPERATOR(pg_catalog.>) 1) +DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT test_table.value, test_table.key, test_table.other_value, cte_1.key, cte_1.other_value FROM (cte_inline.test_table LEFT JOIN (SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb)) cte_1 USING (value)) ORDER BY test_table.value DESC, test_table.key DESC, test_table.other_value DESC LIMIT 3 DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT key, value, other_value, (SELECT 1) FROM (SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb)) cte_1 ORDER BY key DESC, value DESC, other_value DESC LIMIT 3 -DEBUG: Creating router plan - key | value | other_value | ?column? +DEBUG: push down of limit count: 3 + value | key | other_value | key | other_value --------------------------------------------------------------------- - 9 | test99 | | 1 - 9 | test99 | | 1 - 9 | test99 | | 1 + test99 | 9 | | 9 | + test99 | 9 | | 9 | + test99 | 9 | | 9 | (3 rows) EXECUTE non_inlined_cte_has_parameter_on_dist_key(2); DEBUG: CTE cte_1 is going to be inlined via distributed planning DEBUG: Router planner cannot handle multi-shard select queries DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: generating subplan XXX_1 for CTE cte_1: SELECT key, value, other_value FROM cte_inline.test_table WHERE (key OPERATOR(pg_catalog.>) 2) +DEBUG: generating subplan XXX_1 for subquery SELECT key, value, other_value FROM cte_inline.test_table WHERE (key OPERATOR(pg_catalog.>) 2) +DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT test_table.value, test_table.key, test_table.other_value, cte_1.key, cte_1.other_value FROM (cte_inline.test_table LEFT JOIN (SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb)) cte_1 USING (value)) ORDER BY test_table.value DESC, test_table.key DESC, test_table.other_value DESC LIMIT 3 DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT key, value, other_value, (SELECT 1) FROM (SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb)) cte_1 ORDER BY key DESC, value DESC, other_value DESC LIMIT 3 -DEBUG: Creating router plan - key | value | other_value | ?column? +DEBUG: push down of limit count: 3 + value | key | other_value | key | other_value --------------------------------------------------------------------- - 9 | test99 | | 1 - 9 | test99 | | 1 - 9 | test99 | | 1 + test99 | 9 | | 9 | + test99 | 9 | | 9 | + test99 | 9 | | 9 | (3 rows) EXECUTE non_inlined_cte_has_parameter_on_dist_key(3); DEBUG: CTE cte_1 is going to be inlined via distributed planning DEBUG: Router planner cannot handle multi-shard select queries DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: generating subplan XXX_1 for CTE cte_1: SELECT key, value, other_value FROM cte_inline.test_table WHERE (key OPERATOR(pg_catalog.>) 3) +DEBUG: generating subplan XXX_1 for subquery SELECT key, value, other_value FROM cte_inline.test_table WHERE (key OPERATOR(pg_catalog.>) 3) +DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT test_table.value, test_table.key, test_table.other_value, cte_1.key, cte_1.other_value FROM (cte_inline.test_table LEFT JOIN (SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb)) cte_1 USING (value)) ORDER BY test_table.value DESC, test_table.key DESC, test_table.other_value DESC LIMIT 3 DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT key, value, other_value, (SELECT 1) FROM (SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb)) cte_1 ORDER BY key DESC, value DESC, other_value DESC LIMIT 3 -DEBUG: Creating router plan - key | value | other_value | ?column? +DEBUG: push down of limit count: 3 + value | key | other_value | key | other_value --------------------------------------------------------------------- - 9 | test99 | | 1 - 9 | test99 | | 1 - 9 | test99 | | 1 + test99 | 9 | | 9 | + test99 | 9 | | 9 | + test99 | 9 | | 9 | (3 rows) EXECUTE non_inlined_cte_has_parameter_on_dist_key(4); DEBUG: CTE cte_1 is going to be inlined via distributed planning DEBUG: Router planner cannot handle multi-shard select queries DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: generating subplan XXX_1 for CTE cte_1: SELECT key, value, other_value FROM cte_inline.test_table WHERE (key OPERATOR(pg_catalog.>) 4) +DEBUG: generating subplan XXX_1 for subquery SELECT key, value, other_value FROM cte_inline.test_table WHERE (key OPERATOR(pg_catalog.>) 4) +DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT test_table.value, test_table.key, test_table.other_value, cte_1.key, cte_1.other_value FROM (cte_inline.test_table LEFT JOIN (SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb)) cte_1 USING (value)) ORDER BY test_table.value DESC, test_table.key DESC, test_table.other_value DESC LIMIT 3 DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT key, value, other_value, (SELECT 1) FROM (SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb)) cte_1 ORDER BY key DESC, value DESC, other_value DESC LIMIT 3 -DEBUG: Creating router plan - key | value | other_value | ?column? +DEBUG: push down of limit count: 3 + value | key | other_value | key | other_value --------------------------------------------------------------------- - 9 | test99 | | 1 - 9 | test99 | | 1 - 9 | test99 | | 1 + test99 | 9 | | 9 | + test99 | 9 | | 9 | + test99 | 9 | | 9 | (3 rows) EXECUTE non_inlined_cte_has_parameter_on_dist_key(5); DEBUG: CTE cte_1 is going to be inlined via distributed planning DEBUG: Router planner cannot handle multi-shard select queries DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: generating subplan XXX_1 for CTE cte_1: SELECT key, value, other_value FROM cte_inline.test_table WHERE (key OPERATOR(pg_catalog.>) 5) +DEBUG: generating subplan XXX_1 for subquery SELECT key, value, other_value FROM cte_inline.test_table WHERE (key OPERATOR(pg_catalog.>) 5) +DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT test_table.value, test_table.key, test_table.other_value, cte_1.key, cte_1.other_value FROM (cte_inline.test_table LEFT JOIN (SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb)) cte_1 USING (value)) ORDER BY test_table.value DESC, test_table.key DESC, test_table.other_value DESC LIMIT 3 DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT key, value, other_value, (SELECT 1) FROM (SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb)) cte_1 ORDER BY key DESC, value DESC, other_value DESC LIMIT 3 -DEBUG: Creating router plan - key | value | other_value | ?column? +DEBUG: push down of limit count: 3 + value | key | other_value | key | other_value --------------------------------------------------------------------- - 9 | test99 | | 1 - 9 | test99 | | 1 - 9 | test99 | | 1 + test99 | 9 | | 9 | + test99 | 9 | | 9 | + test99 | 9 | | 9 | (3 rows) EXECUTE non_inlined_cte_has_parameter_on_dist_key(6); @@ -1207,15 +1189,15 @@ DEBUG: Router planner cannot handle multi-shard select queries DEBUG: CTE cte_1 is going to be inlined via distributed planning DEBUG: Router planner cannot handle multi-shard select queries DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: generating subplan XXX_1 for CTE cte_1: SELECT key, value, other_value FROM cte_inline.test_table WHERE (key OPERATOR(pg_catalog.>) 6) +DEBUG: generating subplan XXX_1 for subquery SELECT key, value, other_value FROM cte_inline.test_table WHERE (key OPERATOR(pg_catalog.>) 6) +DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT test_table.value, test_table.key, test_table.other_value, cte_1.key, cte_1.other_value FROM (cte_inline.test_table LEFT JOIN (SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb)) cte_1 USING (value)) ORDER BY test_table.value DESC, test_table.key DESC, test_table.other_value DESC LIMIT 3 DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT key, value, other_value, (SELECT 1) FROM (SELECT intermediate_result.key, intermediate_result.value, intermediate_result.other_value FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(key integer, value text, other_value jsonb)) cte_1 ORDER BY key DESC, value DESC, other_value DESC LIMIT 3 -DEBUG: Creating router plan - key | value | other_value | ?column? +DEBUG: push down of limit count: 3 + value | key | other_value | key | other_value --------------------------------------------------------------------- - 9 | test99 | | 1 - 9 | test99 | | 1 - 9 | test99 | | 1 + test99 | 9 | | 9 | + test99 | 9 | | 9 | + test99 | 9 | | 9 | (3 rows) EXECUTE retry_planning(1); diff --git a/src/test/regress/expected/multi_insert_select.out b/src/test/regress/expected/multi_insert_select.out index 1e6e74280..6d2343960 100644 --- a/src/test/regress/expected/multi_insert_select.out +++ b/src/test/regress/expected/multi_insert_select.out @@ -684,15 +684,12 @@ INSERT INTO agg_events DEBUG: CTE sub_cte is going to be inlined via distributed planning DEBUG: Subqueries without relations are not allowed in distributed INSERT ... SELECT queries DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: Subqueries without relations are not allowed in distributed INSERT ... SELECT queries -DEBUG: CTE sub_cte is going to be inlined via distributed planning -DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: Router planner cannot handle multi-shard select queries -DEBUG: generating subplan XXX_1 for CTE sub_cte: SELECT 1 -DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT user_id, (SELECT sub_cte."?column?" FROM (SELECT intermediate_result."?column?" FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result("?column?" integer)) sub_cte("?column?")) AS value_1_agg FROM public.raw_events_first -DEBUG: Router planner cannot handle multi-shard select queries -ERROR: could not run distributed query with subquery outside the FROM, WHERE and HAVING clauses -HINT: Consider using an equality filter on the distributed table's partition column. +DEBUG: performing repartitioned INSERT ... SELECT +DEBUG: partitioning SELECT query by column index 0 with name 'user_id' +DEBUG: distributed statement: INSERT INTO public.agg_events_13300008 AS citus_table_alias (user_id, value_1_agg) SELECT user_id, value_1_agg FROM read_intermediate_results('{repartitioned_results_xxxxx_from_13300000_to_0}'::text[], 'binary'::citus_copy_format) intermediate_result(user_id integer, value_1_agg integer) +DEBUG: distributed statement: INSERT INTO public.agg_events_13300009 AS citus_table_alias (user_id, value_1_agg) SELECT user_id, value_1_agg FROM read_intermediate_results('{repartitioned_results_xxxxx_from_13300001_to_1}'::text[], 'binary'::citus_copy_format) intermediate_result(user_id integer, value_1_agg integer) +DEBUG: distributed statement: INSERT INTO public.agg_events_13300010 AS citus_table_alias (user_id, value_1_agg) SELECT user_id, value_1_agg FROM read_intermediate_results('{repartitioned_results_xxxxx_from_13300002_to_2}'::text[], 'binary'::citus_copy_format) intermediate_result(user_id integer, value_1_agg integer) +DEBUG: distributed statement: INSERT INTO public.agg_events_13300011 AS citus_table_alias (user_id, value_1_agg) SELECT user_id, value_1_agg FROM read_intermediate_results('{repartitioned_results_xxxxx_from_13300003_to_3}'::text[], 'binary'::citus_copy_format) intermediate_result(user_id integer, value_1_agg integer) -- We support set operations via the coordinator BEGIN; INSERT INTO diff --git a/src/test/regress/expected/multi_mx_router_planner.out b/src/test/regress/expected/multi_mx_router_planner.out index ea2d153b0..9486225c5 100644 --- a/src/test/regress/expected/multi_mx_router_planner.out +++ b/src/test/regress/expected/multi_mx_router_planner.out @@ -489,8 +489,7 @@ SELECT a.title AS name, (SELECT a2.id FROM articles_single_shard_hash_mx a2 WHER AS special_price FROM articles_hash_mx a; DEBUG: Router planner cannot handle multi-shard select queries DEBUG: skipping recursive planning for the subquery since it contains references to outer queries -ERROR: could not run distributed query with subquery outside the FROM, WHERE and HAVING clauses -HINT: Consider using an equality filter on the distributed table's partition column. +ERROR: complex joins are only supported when all distributed tables are co-located and joined on their distribution columns -- simple lookup query SELECT * FROM articles_hash_mx diff --git a/src/test/regress/expected/multi_router_planner.out b/src/test/regress/expected/multi_router_planner.out index 73d2f5495..f55c98050 100644 --- a/src/test/regress/expected/multi_router_planner.out +++ b/src/test/regress/expected/multi_router_planner.out @@ -678,8 +678,7 @@ SELECT a.title AS name, (SELECT a2.id FROM articles_single_shard_hash a2 WHERE a AS special_price FROM articles_hash a; DEBUG: Router planner cannot handle multi-shard select queries DEBUG: skipping recursive planning for the subquery since it contains references to outer queries -ERROR: could not run distributed query with subquery outside the FROM, WHERE and HAVING clauses -HINT: Consider using an equality filter on the distributed table's partition column. +ERROR: complex joins are only supported when all distributed tables are co-located and joined on their distribution columns -- simple lookup query SELECT * FROM articles_hash diff --git a/src/test/regress/expected/multi_router_planner_fast_path.out b/src/test/regress/expected/multi_router_planner_fast_path.out index a3ff010cf..003c78162 100644 --- a/src/test/regress/expected/multi_router_planner_fast_path.out +++ b/src/test/regress/expected/multi_router_planner_fast_path.out @@ -424,8 +424,7 @@ SELECT a.title AS name, (SELECT a2.id FROM articles_hash a2 WHERE a.id = a2.id AS special_price FROM articles_hash a; DEBUG: Router planner cannot handle multi-shard select queries DEBUG: skipping recursive planning for the subquery since it contains references to outer queries -ERROR: could not run distributed query with subquery outside the FROM, WHERE and HAVING clauses -HINT: Consider using an equality filter on the distributed table's partition column. +ERROR: complex joins are only supported when all distributed tables are co-located and joined on their distribution columns -- simple lookup query just works SELECT * FROM articles_hash diff --git a/src/test/regress/expected/multi_simple_queries.out b/src/test/regress/expected/multi_simple_queries.out index 98bee6b54..a5d95abd3 100644 --- a/src/test/regress/expected/multi_simple_queries.out +++ b/src/test/regress/expected/multi_simple_queries.out @@ -280,8 +280,7 @@ ORDER BY articles.id; -- subqueries are not supported in SELECT clause SELECT a.title AS name, (SELECT a2.id FROM articles_single_shard a2 WHERE a.id = a2.id LIMIT 1) AS special_price FROM articles a; -ERROR: could not run distributed query with subquery outside the FROM, WHERE and HAVING clauses -HINT: Consider using an equality filter on the distributed table's partition column. +ERROR: complex joins are only supported when all distributed tables are co-located and joined on their distribution columns -- joins are not supported between local and distributed tables SELECT title, authors.name FROM authors, articles WHERE authors.id = articles.author_id; ERROR: direct joins between distributed and local tables are not supported diff --git a/src/test/regress/expected/multi_subquery.out b/src/test/regress/expected/multi_subquery.out index 89260b1d7..1af2b73b0 100644 --- a/src/test/regress/expected/multi_subquery.out +++ b/src/test/regress/expected/multi_subquery.out @@ -702,11 +702,19 @@ WHERE 4968.4946466804019323 (1 row) --- Check unsupported subqueries in target list -SELECT (SELECT 1) FROM orders_subquery; -ERROR: could not run distributed query with subquery outside the FROM, WHERE and HAVING clauses +-- Check subqueries in target list +SELECT (SELECT 1) FROM orders_subquery ORDER BY 1 LIMIT 1; + ?column? +--------------------------------------------------------------------- + 1 +(1 row) + SELECT sum((SELECT 1)) FROM orders_subquery; -ERROR: could not run distributed query with subquery outside the FROM, WHERE and HAVING clauses + sum +--------------------------------------------------------------------- + 2985 +(1 row) + -- Check that if subquery is pulled, we don't error and run query properly. SELECT count(*) FROM ( 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 ea0882400..74fd8a624 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 @@ -62,8 +62,7 @@ WHERE users_reference_table.user_id = events_table.user_id ) LIMIT 3; -ERROR: cannot pushdown the subquery -DETAIL: Reference tables are not allowed in FROM clause when the query has subqueries in WHERE clause and it references a column from another query +ERROR: correlated subqueries are not supported when the FROM clause contains a reference table -- immutable functions are also treated as reference tables, query should not -- work since there is a correlated subquery in the WHERE clause SELECT @@ -80,8 +79,7 @@ WHERE users_reference_table.user_id = events_table.user_id ) LIMIT 3; -ERROR: cannot pushdown the subquery -DETAIL: Functions are not allowed in FROM clause when the query has subqueries in WHERE clause and it references a column from another query +ERROR: correlated subqueries are not supported when the FROM clause contains a set returning function -- subqueries without FROM are also treated as reference tables, query should not -- work since there is a correlated subquery in the WHERE clause SELECT @@ -98,8 +96,7 @@ WHERE users_reference_table.user_id = events_table.user_id ) LIMIT 3; -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 +ERROR: correlated subqueries are not supported when the FROM clause contains a CTE or subquery -- join with distributed table prevents FROM from recurring SELECT DISTINCT user_id @@ -528,8 +525,7 @@ HAVING count(*) > 3 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 and it references a column from another query +ERROR: correlated subqueries are not supported when the FROM clause contains a reference table -- query will be planned as a SEMI JOIN SELECT * FROM users_table diff --git a/src/test/regress/expected/multi_utility_statements.out b/src/test/regress/expected/multi_utility_statements.out index b900a106d..017874842 100644 --- a/src/test/regress/expected/multi_utility_statements.out +++ b/src/test/regress/expected/multi_utility_statements.out @@ -290,9 +290,7 @@ RETURNS void AS $$ DECLARE c4 CURSOR WITH HOLD FOR SELECT *, (SELECT 1) FROM cursor_me WHERE x = $1; $$ LANGUAGE SQL; SELECT declares_cursor_4(19); -ERROR: could not run distributed query with subquery outside the FROM, WHERE and HAVING clauses -HINT: Consider using an equality filter on the distributed table's partition column. -CONTEXT: SQL function "declares_cursor_4" statement 1 +ERROR: Cursors for queries on distributed tables with parameters are currently unsupported CREATE OR REPLACE FUNCTION cursor_plpgsql(p int) RETURNS SETOF int AS $$ DECLARE diff --git a/src/test/regress/expected/subquery_in_targetlist.out b/src/test/regress/expected/subquery_in_targetlist.out new file mode 100644 index 000000000..d3352e32a --- /dev/null +++ b/src/test/regress/expected/subquery_in_targetlist.out @@ -0,0 +1,431 @@ +CREATE SCHEMA subquery_in_targetlist; +SET search_path TO subquery_in_targetlist, public; +-- simple empty target list +SELECT event_type, (SELECT 1 + 3 + e.value_2) +FROM events_table e +ORDER BY 1,2 LIMIT 1; + event_type | ?column? +--------------------------------------------------------------------- + 0 | 4 +(1 row) + +-- simple reference table sublink +SELECT event_type, (SELECT user_id FROM users_reference_table WHERE user_id = 1 AND value_1 = 1) +FROM events_table e +ORDER BY 1,2 LIMIT 1; + event_type | user_id +--------------------------------------------------------------------- + 0 | 1 +(1 row) + +-- duplicate vars +SELECT event_type, (SELECT e.value_2 FROM users_reference_table WHERE user_id = 1 AND value_1 = 1), (SELECT e.value_2) +FROM events_table e +ORDER BY 1,2 LIMIT 1; + event_type | value_2 | value_2 +--------------------------------------------------------------------- + 0 | 0 | 0 +(1 row) + +-- correlated subquery with aggregate +SELECT event_type, (SELECT max(time) FROM users_table WHERE user_id = e.user_id) +FROM events_table e +ORDER BY 1,2 LIMIT 1; +ERROR: cannot push down this subquery +DETAIL: Aggregates without group by are currently unsupported when a subquery references a column from another query +-- correlated subquery wtth limit +SELECT event_type, (SELECT time FROM users_table WHERE user_id = e.user_id ORDER BY time LIMIT 1) +FROM events_table e +ORDER BY 1,2 LIMIT 1; +ERROR: cannot push down this subquery +DETAIL: Limit in subquery is currently unsupported when a subquery references a column from another query +-- correlated subquery with group by distribution column +SELECT event_type, (SELECT max(time) FROM users_table WHERE user_id = e.user_id GROUP BY user_id) +FROM events_table e +ORDER BY 1,2 LIMIT 1; + event_type | max +--------------------------------------------------------------------- + 0 | Thu Nov 23 13:52:54.83829 2017 +(1 row) + +-- correlated subquery with group by almost distribution column +SELECT event_type, (SELECT max(time) FROM users_table WHERE user_id = e.user_id GROUP BY e.user_id) +FROM events_table e +ORDER BY 1,2 LIMIT 1; +ERROR: cannot push down this subquery +DETAIL: Group by list without partition column is currently unsupported when a subquery references a column from another query +-- correlated subquery co-located join in outer query +SELECT event_type, (SELECT max(time) FROM users_table WHERE user_id = e.user_id GROUP BY user_id) +FROM users_table u JOIN events_table e USING (user_id) +ORDER BY 1,2 LIMIT 1; + event_type | max +--------------------------------------------------------------------- + 0 | Thu Nov 23 13:52:54.83829 2017 +(1 row) + +-- correlated subquery non-co-located join in outer query +SELECT event_type, (SELECT max(time) FROM users_table WHERE user_id = e.user_id GROUP BY user_id) +FROM users_table u JOIN events_table e USING (value_2) +ORDER BY 1,2 LIMIT 1; +ERROR: complex joins are only supported when all distributed tables are co-located and joined on their distribution columns +-- correlated subuqery with non-co-located join +SELECT event_type, (SELECT max(time) FROM users_table WHERE user_id = e.value_2) +FROM events_table e +ORDER BY 1,2 LIMIT 1; +ERROR: complex joins are only supported when all distributed tables are co-located and joined on their distribution columns +SELECT event_type, (SELECT max(time) FROM users_table WHERE user_id = e.value_2 GROUP BY user_id) +FROM events_table e +ORDER BY 1,2 LIMIT 1; +ERROR: complex joins are only supported when all distributed tables are co-located and joined on their distribution columns +-- correlated subquery with reference table and aggregate +SELECT event_type, (SELECT max(time) FROM users_reference_table WHERE user_id = e.value_2) +FROM events_table e +ORDER BY 1,2 LIMIT 1; +ERROR: cannot push down this subquery +DETAIL: Aggregates without group by are currently unsupported when a subquery references a column from another query +-- correlated subquery with reference table and group by +SELECT event_type, (SELECT max(time) FROM users_reference_table WHERE user_id = e.value_2 GROUP BY user_id) +FROM events_table e +ORDER BY 1,2 LIMIT 1; + event_type | max +--------------------------------------------------------------------- + 0 | Thu Nov 23 13:52:54.83829 2017 +(1 row) + +-- correlated subquery with reference table join +SELECT (SELECT max(u1.time) FROM users_table u1 JOIN users_reference_table u2 USING (user_id) WHERE u2.user_id = e.user_id GROUP BY user_id), 5 +FROM events_table e +GROUP BY 1 +ORDER BY 1,2 LIMIT 1; + max | ?column? +--------------------------------------------------------------------- + Thu Nov 23 13:52:54.83829 2017 | 5 +(1 row) + +-- correlated subquery with reference table join and reference table in outer query +SELECT (SELECT max(u1.time) FROM users_table u1 JOIN users_reference_table u2 USING (user_id) WHERE u2.user_id = e.user_id GROUP BY user_id), 5 +FROM events_reference_table e +GROUP BY 1 +ORDER BY 1,2 LIMIT 1; +ERROR: correlated subqueries are not supported when the FROM clause contains a reference table +-- correlated subquery with non-co-located join in outer query +SELECT event_type, (SELECT max(time) FROM users_table WHERE user_id = e.user_id GROUP BY user_id) +FROM users_table u JOIN events_table e USING (value_2) +ORDER BY 1,2 LIMIT 1; +ERROR: complex joins are only supported when all distributed tables are co-located and joined on their distribution columns +-- aggregate in sublink without join +SELECT event_type, (SELECT max(time) FROM users_table) +FROM events_table e +ORDER BY 1,2 LIMIT 1; + event_type | max +--------------------------------------------------------------------- + 0 | Thu Nov 23 17:30:34.635085 2017 +(1 row) + +-- aggregate in ctes in sublink +WITH cte_1 AS (SELECT max(time) FROM users_table) +SELECT event_type, (SELECT * FROM cte_1) +FROM events_table e +ORDER BY 1,2 LIMIT 1; + event_type | max +--------------------------------------------------------------------- + 0 | Thu Nov 23 17:30:34.635085 2017 +(1 row) + +-- aggregate in ctes in sublink with limit +WITH cte_1 AS (SELECT max(time) FROM users_table) +SELECT event_type, (SELECT * FROM cte_1 LIMIT 1) +FROM events_table e +ORDER BY 1,2 LIMIT 1; + event_type | max +--------------------------------------------------------------------- + 0 | Thu Nov 23 17:30:34.635085 2017 +(1 row) + +-- aggregate in ctes in sublink with join +WITH cte_1 AS (SELECT max(time) m FROM users_table) +SELECT count(*), (SELECT * FROM cte_1 c1 join cte_1 c2 using (m)) +FROM events_table e +GROUP BY 2 +ORDER BY 1,2 LIMIT 1; + count | m +--------------------------------------------------------------------- + 101 | Thu Nov 23 17:30:34.635085 2017 +(1 row) + +-- correlated subquery with cte in outer query +WITH cte_1 AS (SELECT min(user_id) u, max(time) m FROM users_table) +SELECT count(*), (SELECT max(time) FROM users_table WHERE user_id = cte_1.u GROUP BY user_id) +FROM cte_1 +GROUP BY 2 +ORDER BY 1,2 LIMIT 1; +ERROR: correlated subqueries are not supported when the FROM clause contains a CTE or subquery +-- correlated subquery in an aggregate +SELECT sum((SELECT max(value_3) FROM users_table WHERE user_id = e.user_id GROUP BY user_id)) +FROM events_table e; + sum +--------------------------------------------------------------------- + 490 +(1 row) + +-- correlated subquery outside of an aggregate +SELECT sum(e.user_id) + (SELECT max(value_3) FROM users_table WHERE user_id = e.user_id GROUP BY user_id) +FROM events_table e +GROUP BY e.user_id +ORDER BY 1 LIMIT 3; +ERROR: cannot push down subquery on the target list +DETAIL: Subqueries in the SELECT part of the query can only be pushed down if they happen before aggregates and window functions +-- subquery outside of an aggregate +SELECT sum(e.user_id) + (SELECT user_id FROM users_reference_table WHERE user_id = 1 AND value_1 = 1) +FROM events_table e; +ERROR: cannot push down subquery on the target list +DETAIL: Subqueries in the SELECT part of the query can only be pushed down if they happen before aggregates and window functions +-- sublink in a pushdownable window function +SELECT e.user_id, sum((SELECT any_value(value_3) FROM users_reference_table WHERE user_id = e.user_id GROUP BY user_id)) OVER (PARTITION BY e.user_id) +FROM events_table e +ORDER BY 1, 2 LIMIT 3; + user_id | sum +--------------------------------------------------------------------- + 1 | 60 + 1 | 60 + 1 | 60 +(3 rows) + +-- sublink in a non-pushdownable window function +SELECT e.value_2, sum((SELECT any_value(value_3) FROM users_reference_table WHERE user_id = e.user_id GROUP BY user_id)) OVER (PARTITION BY e.value_2) +FROM events_table e +ORDER BY 1, 2 LIMIT 3; +ERROR: cannot push down subquery on the target list +DETAIL: Subqueries in the SELECT part of the query can only be pushed down if they happen before aggregates and window functions +-- sublink in a group by expression +SELECT e.value_2 + (SELECT any_value(value_3) FROM users_reference_table WHERE user_id = e.user_id GROUP BY user_id) +FROM events_table e +GROUP BY 1 +ORDER BY 1 LIMIT 3; + ?column? +--------------------------------------------------------------------- + 0 + 1 + 2 +(3 rows) + +-- sublink in sublink +SELECT (SELECT (SELECT user_id + 2) * 2 FROM users_table WHERE user_id = e.user_id GROUP BY user_id) +FROM events_table e +GROUP BY 1 +ORDER BY 1 LIMIT 3; + ?column? +--------------------------------------------------------------------- + 6 + 8 + 10 +(3 rows) + +-- sublink in sublink with outer table reference +SELECT (SELECT (SELECT e.user_id + user_id) FROM users_table WHERE user_id = e.user_id GROUP BY user_id) +FROM events_table e +GROUP BY 1 +ORDER BY 1 LIMIT 3; + ?column? +--------------------------------------------------------------------- + 2 + 4 + 6 +(3 rows) + +-- sublink in sublink with reference table +SELECT (SELECT (SELECT e.user_id + user_id) FROM users_reference_table WHERE user_id = e.user_id GROUP BY user_id) +FROM events_table e +GROUP BY 1 +ORDER BY 1 LIMIT 3; +ERROR: correlated subqueries are not supported when the FROM clause contains a reference table +-- sublink in sublink with cte +WITH cte_1 AS (SELECT user_id FROM users_table ORDER BY 1 LIMIT 1) +SELECT (SELECT (SELECT e.user_id + user_id) FROM cte_1 WHERE user_id = e.user_id GROUP BY user_id) +FROM events_table e +GROUP BY 1 +ORDER BY 1 LIMIT 3; +ERROR: correlated subqueries are not supported when the FROM clause contains a CTE or subquery +-- sublink in sublink +SELECT (SELECT (SELECT e.user_id + user_id) FROM (SELECT 1 AS user_id) s WHERE user_id = e.user_id GROUP BY user_id) +FROM events_table e +GROUP BY 1 +ORDER BY 1 LIMIT 3; +ERROR: correlated subqueries are not supported when the FROM clause contains a subquery without FROM +-- sublink on view +CREATE TEMP VIEW view_1 AS (SELECT user_id, value_2 FROM users_table WHERE user_id = 1 AND value_1 = 1 ORDER BY 1,2); +-- with distribution column group by +SELECT (SELECT value_2 FROM view_1 WHERE user_id = e.user_id GROUP BY user_id, value_2) +FROM events_table e +GROUP BY 1 +ORDER BY 1 LIMIT 3; + value_2 +--------------------------------------------------------------------- + 3 + +(2 rows) + +-- without distribution column group by +SELECT (SELECT value_2 FROM view_1 WHERE user_id = e.user_id GROUP BY value_2) +FROM events_table e +GROUP BY 1 +ORDER BY 1 LIMIT 3; +ERROR: cannot push down this subquery +DETAIL: Group by list without partition column is currently unsupported when a subquery references a column from another query +-- without view in the outer query FROM +SELECT (SELECT value_2 FROM view_1 WHERE user_id = e.user_id GROUP BY user_id, value_2) +FROM view_1 e +GROUP BY 1 +ORDER BY 1 LIMIT 3; + value_2 +--------------------------------------------------------------------- + 3 +(1 row) + +-- sublink in sublink on view +SELECT (SELECT (SELECT e.user_id + user_id) FROM view_1 WHERE user_id = e.user_id GROUP BY user_id) +FROM events_table e +GROUP BY 1 +ORDER BY 1 LIMIT 3; + ?column? +--------------------------------------------------------------------- + 2 + +(2 rows) + +-- sublink on reference table view +CREATE TEMP VIEW view_2 AS (SELECT user_id, value_2 FROM users_reference_table WHERE user_id = 1 AND value_1 = 1); +SELECT (SELECT value_2 FROM view_2 WHERE user_id = e.user_id GROUP BY user_id, value_2) +FROM events_table e +GROUP BY 1 +ORDER BY 1 LIMIT 3; + value_2 +--------------------------------------------------------------------- + 3 + +(2 rows) + +-- without distributed table view in FROM, reference table view in sublink +SELECT (SELECT value_2 FROM view_2 WHERE user_id = e.user_id GROUP BY user_id, value_2) +FROM view_1 e +GROUP BY 1 +ORDER BY 1 LIMIT 3; + value_2 +--------------------------------------------------------------------- + 3 +(1 row) + +-- without reference table view in FROM, distributed in sublink +SELECT (SELECT value_2 FROM view_1 WHERE user_id = e.user_id GROUP BY user_id, value_2) +FROM view_2 e +GROUP BY 1 +ORDER BY 1 LIMIT 3; + value_2 +--------------------------------------------------------------------- + 3 +(1 row) + +-- use view as a type +SELECT (SELECT view_1) +FROM view_1 +ORDER BY 1 LIMIT 1; +ERROR: type "view_1" does not exist +CONTEXT: while executing command on localhost:xxxxx +-- nested correlated sublink +SELECT (SELECT (SELECT user_id)) +FROM events_table e +ORDER BY 1 LIMIT 1; +ERROR: correlated subqueries are not supported when the FROM clause contains a subquery without FROM +-- sublink with record type +SELECT (SELECT u FROM users_table u WHERE u.user_id = e.user_id AND time = 'Thu Nov 23 09:26:42.145043 2017') +FROM events_table e +GROUP BY 1 +ORDER BY 1 LIMIT 3; + u +--------------------------------------------------------------------- + (1,"Thu Nov 23 09:26:42.145043 2017",1,3,3,) + +(2 rows) + +-- sublink with anonymous record type +SELECT (SELECT (user_id,value_1) FROM users_table u WHERE u.user_id = e.user_id AND time = 'Thu Nov 23 09:26:42.145043 2017') +FROM events_table e +WHERE user_id < 3 +GROUP BY 1 +ORDER BY 1 LIMIT 3; +ERROR: input of anonymous composite types is not implemented +-- complex query using row_to_json +SELECT coalesce(json_agg(root ORDER BY user_id), '[]') AS root +FROM + (SELECT row_to_json( + (SELECT _1_e + FROM + (SELECT "_0_root.base".user_id AS user_id) AS _1_e)) AS root, user_id + FROM + (SELECT DISTINCT user_id FROM public.users_table ORDER BY 1) AS "_0_root.base") AS _2_root ; + root +--------------------------------------------------------------------- + [{"user_id":1}, {"user_id":2}, {"user_id":3}, {"user_id":4}, {"user_id":5}, {"user_id":6}] +(1 row) + +SELECT * +FROM + (SELECT + row_to_json((SELECT _1_e FROM (SELECT user_id) AS _1_e)) AS root, user_id + FROM + (SELECT DISTINCT user_id FROM public.users_table ORDER BY 1) as bar) AS foo ORDER BY user_id; + root | user_id +--------------------------------------------------------------------- + {"user_id":1} | 1 + {"user_id":2} | 2 + {"user_id":3} | 3 + {"user_id":4} | 4 + {"user_id":5} | 5 + {"user_id":6} | 6 +(6 rows) + +-- non-colocated subquery join +SELECT count(*) FROM + (SELECT event_type, (SELECT e.value_2 FROM users_reference_table WHERE user_id = 1 AND value_1 = 1 AND value_2 = 1), (SELECT e.value_2) + FROM events_table e) as foo + JOIN + (SELECT event_type, (SELECT e.value_2 FROM users_reference_table WHERE user_id = 5 AND value_1 = 1 AND value_2 = 1), (SELECT e.value_2) + FROM events_table e) as bar + ON bar.event_type = foo.event_type; + count +--------------------------------------------------------------------- + 1993 +(1 row) + +-- subquery in the target list in HAVING should be fine +SELECT + user_id, count(*) +FROM + events_table e1 +GROUP BY user_id + HAVING + count(*) > (SELECT count(*) FROM (SELECT + (SELECT sum(user_id) FROM users_table WHERE user_id = u1.user_id GROUP BY user_id) + FROM users_table u1 + GROUP BY user_id) as foo) ORDER BY 1 DESC; + user_id | count +--------------------------------------------------------------------- + 6 | 10 + 5 | 14 + 4 | 17 + 3 | 21 + 2 | 24 + 1 | 15 +(6 rows) + +-- make sure that we don't pushdown subqueries in the target list if no FROM clause +SELECT (SELECT DISTINCT user_id FROM users_table WHERE user_id = (SELECT max(user_id) FROM users_table )); +ERROR: correlated subqueries are not supported when the FROM clause contains a subquery without FROM +-- not meaningful SELECT FOR UPDATE query that should fail +SELECT count(*) FROM (SELECT + (SELECT user_id FROM users_table WHERE user_id = u1.user_id FOR UPDATE) +FROM users_table u1 +GROUP BY user_id) as foo; +ERROR: cannot push down this subquery +DETAIL: For Update/Share commands are currently unsupported +DROP SCHEMA subquery_in_targetlist CASCADE; diff --git a/src/test/regress/expected/subquery_in_where.out b/src/test/regress/expected/subquery_in_where.out index b15e31bd1..39221a7e5 100644 --- a/src/test/regress/expected/subquery_in_where.out +++ b/src/test/regress/expected/subquery_in_where.out @@ -39,8 +39,7 @@ WHERE events_user_id IN (SELECT user_id DEBUG: CTE event_id is going to be inlined via distributed planning DEBUG: generating subplan XXX_1 for CTE event_id: SELECT user_id AS events_user_id, "time" AS events_time, event_type FROM public.events_table DEBUG: Plan XXX 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('XXX_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 OPERATOR(pg_catalog.=) ANY (SELECT users_table.user_id FROM public.users_table WHERE (users_table."time" OPERATOR(pg_catalog.=) 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 +ERROR: correlated subqueries are not supported when the FROM clause contains a CTE or subquery -- Recurring tuples as empty join tree SELECT * FROM (SELECT 1 AS id, 2 AS value_1, 3 AS value_3 diff --git a/src/test/regress/expected/with_basics.out b/src/test/regress/expected/with_basics.out index ce66ec103..d921d203c 100644 --- a/src/test/regress/expected/with_basics.out +++ b/src/test/regress/expected/with_basics.out @@ -95,21 +95,26 @@ SELECT user_id FROM ( 2 (3 rows) --- CTE outside of FROM/WHERE errors out +-- CTE outside of FROM/WHERE errors WITH cte AS ( SELECT user_id FROM users_table WHERE value_2 IN (1, 2) ) SELECT (SELECT * FROM cte); ERROR: more than one row returned by a subquery used as an expression WITH cte_basic AS ( - SELECT user_id FROM users_table WHERE user_id = 1 + SELECT user_id FROM users_table WHERE user_id = 1 LIMIT 1 ) SELECT (SELECT user_id FROM cte_basic), user_id FROM - users_table; -ERROR: could not run distributed query with subquery outside the FROM, WHERE and HAVING clauses -HINT: Consider using an equality filter on the distributed table's partition column. + users_table +ORDER BY 1,2 +LIMIT 1; + user_id | user_id +--------------------------------------------------------------------- + 1 | 1 +(1 row) + -- single-row sublink is acceptable when there is no FROM WITH cte AS ( SELECT user_id FROM users_table WHERE value_2 IN (1, 2) diff --git a/src/test/regress/multi_schedule b/src/test/regress/multi_schedule index 34dd4986d..95434bf38 100644 --- a/src/test/regress/multi_schedule +++ b/src/test/regress/multi_schedule @@ -83,7 +83,8 @@ test: subquery_and_cte test: set_operations test: set_operation_and_local_tables -test: subqueries_deep subquery_view subquery_partitioning subquery_complex_target_list subqueries_not_supported subquery_in_where +test: subqueries_deep subquery_view subquery_partitioning subqueries_not_supported +test: subquery_in_targetlist subquery_in_where subquery_complex_target_list test: subquery_prepared_statements test: non_colocated_leaf_subquery_joins non_colocated_subquery_joins non_colocated_join_order test: cte_inline recursive_view_local_table diff --git a/src/test/regress/sql/cte_inline.sql b/src/test/regress/sql/cte_inline.sql index bf0d9885d..a72d75039 100644 --- a/src/test/regress/sql/cte_inline.sql +++ b/src/test/regress/sql/cte_inline.sql @@ -17,17 +17,17 @@ SET client_min_messages TO DEBUG; -- plan the query WITH cte_1 AS (SELECT * FROM test_table) SELECT - *, (SELECT 1) + * FROM - cte_1 + test_table LEFT JOIN cte_1 USING (value) ORDER BY 1 DESC LIMIT 3; -- Should still not be inlined even if NOT MATERIALIZED is passed WITH cte_1 AS NOT MATERIALIZED (SELECT * FROM test_table) SELECT - *, (SELECT 1) + * FROM - cte_1 + test_table LEFT JOIN cte_1 USING (value) ORDER BY 2 DESC LIMIT 1; -- the cte can be inlined because the unsupported @@ -494,9 +494,9 @@ PREPARE inlined_cte_without_params AS PREPARE non_inlined_cte_without_params AS WITH cte_1 AS (SELECT * FROM test_table) SELECT - *, (SELECT 1) + * FROM - cte_1 ORDER BY 1 DESC, 2 DESC, 3 DESC LIMIT 3; + test_table LEFT JOIN cte_1 USING (value) ORDER BY 1 DESC, 2 DESC, 3 DESC LIMIT 3; PREPARE inlined_cte_has_parameter_on_non_dist_key(text) AS WITH cte_1 AS (SELECT count(*) FROM test_table WHERE value = $1 GROUP BY key) SELECT * FROM cte_1 ORDER BY 1 DESC LIMIT 3; @@ -506,9 +506,9 @@ PREPARE inlined_cte_has_parameter_on_dist_key(int) AS PREPARE non_inlined_cte_has_parameter_on_dist_key(int) AS WITH cte_1 AS (SELECT * FROM test_table where key > $1) SELECT - *, (SELECT 1) + * FROM - cte_1 ORDER BY 1 DESC, 2 DESC, 3 DESC LIMIT 3; + test_table LEFT JOIN cte_1 USING (value) ORDER BY 1 DESC, 2 DESC, 3 DESC LIMIT 3; PREPARE retry_planning(int) AS WITH cte_1 AS (SELECT * FROM test_table WHERE key > $1) SELECT json_object_agg(DISTINCT key, value) FROM cte_1 ORDER BY max(key), min(value) DESC LIMIT 3; diff --git a/src/test/regress/sql/multi_subquery.sql b/src/test/regress/sql/multi_subquery.sql index eb47ce0d0..68265606a 100644 --- a/src/test/regress/sql/multi_subquery.sql +++ b/src/test/regress/sql/multi_subquery.sql @@ -468,8 +468,8 @@ WHERE unit_price > 1000 AND unit_price < 10000; --- Check unsupported subqueries in target list -SELECT (SELECT 1) FROM orders_subquery; +-- Check subqueries in target list +SELECT (SELECT 1) FROM orders_subquery ORDER BY 1 LIMIT 1; SELECT sum((SELECT 1)) FROM orders_subquery; -- Check that if subquery is pulled, we don't error and run query properly. diff --git a/src/test/regress/sql/subquery_in_targetlist.sql b/src/test/regress/sql/subquery_in_targetlist.sql new file mode 100644 index 000000000..8245c1a2a --- /dev/null +++ b/src/test/regress/sql/subquery_in_targetlist.sql @@ -0,0 +1,294 @@ +CREATE SCHEMA subquery_in_targetlist; +SET search_path TO subquery_in_targetlist, public; + +-- simple empty target list +SELECT event_type, (SELECT 1 + 3 + e.value_2) +FROM events_table e +ORDER BY 1,2 LIMIT 1; + +-- simple reference table sublink +SELECT event_type, (SELECT user_id FROM users_reference_table WHERE user_id = 1 AND value_1 = 1) +FROM events_table e +ORDER BY 1,2 LIMIT 1; + +-- duplicate vars +SELECT event_type, (SELECT e.value_2 FROM users_reference_table WHERE user_id = 1 AND value_1 = 1), (SELECT e.value_2) +FROM events_table e +ORDER BY 1,2 LIMIT 1; + +-- correlated subquery with aggregate +SELECT event_type, (SELECT max(time) FROM users_table WHERE user_id = e.user_id) +FROM events_table e +ORDER BY 1,2 LIMIT 1; + +-- correlated subquery wtth limit +SELECT event_type, (SELECT time FROM users_table WHERE user_id = e.user_id ORDER BY time LIMIT 1) +FROM events_table e +ORDER BY 1,2 LIMIT 1; + +-- correlated subquery with group by distribution column +SELECT event_type, (SELECT max(time) FROM users_table WHERE user_id = e.user_id GROUP BY user_id) +FROM events_table e +ORDER BY 1,2 LIMIT 1; + +-- correlated subquery with group by almost distribution column +SELECT event_type, (SELECT max(time) FROM users_table WHERE user_id = e.user_id GROUP BY e.user_id) +FROM events_table e +ORDER BY 1,2 LIMIT 1; + +-- correlated subquery co-located join in outer query +SELECT event_type, (SELECT max(time) FROM users_table WHERE user_id = e.user_id GROUP BY user_id) +FROM users_table u JOIN events_table e USING (user_id) +ORDER BY 1,2 LIMIT 1; + +-- correlated subquery non-co-located join in outer query +SELECT event_type, (SELECT max(time) FROM users_table WHERE user_id = e.user_id GROUP BY user_id) +FROM users_table u JOIN events_table e USING (value_2) +ORDER BY 1,2 LIMIT 1; + +-- correlated subuqery with non-co-located join +SELECT event_type, (SELECT max(time) FROM users_table WHERE user_id = e.value_2) +FROM events_table e +ORDER BY 1,2 LIMIT 1; + +SELECT event_type, (SELECT max(time) FROM users_table WHERE user_id = e.value_2 GROUP BY user_id) +FROM events_table e +ORDER BY 1,2 LIMIT 1; + +-- correlated subquery with reference table and aggregate +SELECT event_type, (SELECT max(time) FROM users_reference_table WHERE user_id = e.value_2) +FROM events_table e +ORDER BY 1,2 LIMIT 1; + +-- correlated subquery with reference table and group by +SELECT event_type, (SELECT max(time) FROM users_reference_table WHERE user_id = e.value_2 GROUP BY user_id) +FROM events_table e +ORDER BY 1,2 LIMIT 1; + +-- correlated subquery with reference table join +SELECT (SELECT max(u1.time) FROM users_table u1 JOIN users_reference_table u2 USING (user_id) WHERE u2.user_id = e.user_id GROUP BY user_id), 5 +FROM events_table e +GROUP BY 1 +ORDER BY 1,2 LIMIT 1; + +-- correlated subquery with reference table join and reference table in outer query +SELECT (SELECT max(u1.time) FROM users_table u1 JOIN users_reference_table u2 USING (user_id) WHERE u2.user_id = e.user_id GROUP BY user_id), 5 +FROM events_reference_table e +GROUP BY 1 +ORDER BY 1,2 LIMIT 1; + +-- correlated subquery with non-co-located join in outer query +SELECT event_type, (SELECT max(time) FROM users_table WHERE user_id = e.user_id GROUP BY user_id) +FROM users_table u JOIN events_table e USING (value_2) +ORDER BY 1,2 LIMIT 1; + +-- aggregate in sublink without join +SELECT event_type, (SELECT max(time) FROM users_table) +FROM events_table e +ORDER BY 1,2 LIMIT 1; + +-- aggregate in ctes in sublink +WITH cte_1 AS (SELECT max(time) FROM users_table) +SELECT event_type, (SELECT * FROM cte_1) +FROM events_table e +ORDER BY 1,2 LIMIT 1; + +-- aggregate in ctes in sublink with limit +WITH cte_1 AS (SELECT max(time) FROM users_table) +SELECT event_type, (SELECT * FROM cte_1 LIMIT 1) +FROM events_table e +ORDER BY 1,2 LIMIT 1; + +-- aggregate in ctes in sublink with join +WITH cte_1 AS (SELECT max(time) m FROM users_table) +SELECT count(*), (SELECT * FROM cte_1 c1 join cte_1 c2 using (m)) +FROM events_table e +GROUP BY 2 +ORDER BY 1,2 LIMIT 1; + +-- correlated subquery with cte in outer query +WITH cte_1 AS (SELECT min(user_id) u, max(time) m FROM users_table) +SELECT count(*), (SELECT max(time) FROM users_table WHERE user_id = cte_1.u GROUP BY user_id) +FROM cte_1 +GROUP BY 2 +ORDER BY 1,2 LIMIT 1; + +-- correlated subquery in an aggregate +SELECT sum((SELECT max(value_3) FROM users_table WHERE user_id = e.user_id GROUP BY user_id)) +FROM events_table e; + +-- correlated subquery outside of an aggregate +SELECT sum(e.user_id) + (SELECT max(value_3) FROM users_table WHERE user_id = e.user_id GROUP BY user_id) +FROM events_table e +GROUP BY e.user_id +ORDER BY 1 LIMIT 3; + +-- subquery outside of an aggregate +SELECT sum(e.user_id) + (SELECT user_id FROM users_reference_table WHERE user_id = 1 AND value_1 = 1) +FROM events_table e; + +-- sublink in a pushdownable window function +SELECT e.user_id, sum((SELECT any_value(value_3) FROM users_reference_table WHERE user_id = e.user_id GROUP BY user_id)) OVER (PARTITION BY e.user_id) +FROM events_table e +ORDER BY 1, 2 LIMIT 3; + +-- sublink in a non-pushdownable window function +SELECT e.value_2, sum((SELECT any_value(value_3) FROM users_reference_table WHERE user_id = e.user_id GROUP BY user_id)) OVER (PARTITION BY e.value_2) +FROM events_table e +ORDER BY 1, 2 LIMIT 3; + +-- sublink in a group by expression +SELECT e.value_2 + (SELECT any_value(value_3) FROM users_reference_table WHERE user_id = e.user_id GROUP BY user_id) +FROM events_table e +GROUP BY 1 +ORDER BY 1 LIMIT 3; + +-- sublink in sublink +SELECT (SELECT (SELECT user_id + 2) * 2 FROM users_table WHERE user_id = e.user_id GROUP BY user_id) +FROM events_table e +GROUP BY 1 +ORDER BY 1 LIMIT 3; + +-- sublink in sublink with outer table reference +SELECT (SELECT (SELECT e.user_id + user_id) FROM users_table WHERE user_id = e.user_id GROUP BY user_id) +FROM events_table e +GROUP BY 1 +ORDER BY 1 LIMIT 3; + +-- sublink in sublink with reference table +SELECT (SELECT (SELECT e.user_id + user_id) FROM users_reference_table WHERE user_id = e.user_id GROUP BY user_id) +FROM events_table e +GROUP BY 1 +ORDER BY 1 LIMIT 3; + +-- sublink in sublink with cte +WITH cte_1 AS (SELECT user_id FROM users_table ORDER BY 1 LIMIT 1) +SELECT (SELECT (SELECT e.user_id + user_id) FROM cte_1 WHERE user_id = e.user_id GROUP BY user_id) +FROM events_table e +GROUP BY 1 +ORDER BY 1 LIMIT 3; + +-- sublink in sublink +SELECT (SELECT (SELECT e.user_id + user_id) FROM (SELECT 1 AS user_id) s WHERE user_id = e.user_id GROUP BY user_id) +FROM events_table e +GROUP BY 1 +ORDER BY 1 LIMIT 3; + +-- sublink on view +CREATE TEMP VIEW view_1 AS (SELECT user_id, value_2 FROM users_table WHERE user_id = 1 AND value_1 = 1 ORDER BY 1,2); + +-- with distribution column group by +SELECT (SELECT value_2 FROM view_1 WHERE user_id = e.user_id GROUP BY user_id, value_2) +FROM events_table e +GROUP BY 1 +ORDER BY 1 LIMIT 3; + +-- without distribution column group by +SELECT (SELECT value_2 FROM view_1 WHERE user_id = e.user_id GROUP BY value_2) +FROM events_table e +GROUP BY 1 +ORDER BY 1 LIMIT 3; + +-- without view in the outer query FROM +SELECT (SELECT value_2 FROM view_1 WHERE user_id = e.user_id GROUP BY user_id, value_2) +FROM view_1 e +GROUP BY 1 +ORDER BY 1 LIMIT 3; + +-- sublink in sublink on view +SELECT (SELECT (SELECT e.user_id + user_id) FROM view_1 WHERE user_id = e.user_id GROUP BY user_id) +FROM events_table e +GROUP BY 1 +ORDER BY 1 LIMIT 3; + +-- sublink on reference table view +CREATE TEMP VIEW view_2 AS (SELECT user_id, value_2 FROM users_reference_table WHERE user_id = 1 AND value_1 = 1); +SELECT (SELECT value_2 FROM view_2 WHERE user_id = e.user_id GROUP BY user_id, value_2) +FROM events_table e +GROUP BY 1 +ORDER BY 1 LIMIT 3; + +-- without distributed table view in FROM, reference table view in sublink +SELECT (SELECT value_2 FROM view_2 WHERE user_id = e.user_id GROUP BY user_id, value_2) +FROM view_1 e +GROUP BY 1 +ORDER BY 1 LIMIT 3; + +-- without reference table view in FROM, distributed in sublink +SELECT (SELECT value_2 FROM view_1 WHERE user_id = e.user_id GROUP BY user_id, value_2) +FROM view_2 e +GROUP BY 1 +ORDER BY 1 LIMIT 3; + +-- use view as a type +SELECT (SELECT view_1) +FROM view_1 +ORDER BY 1 LIMIT 1; + +-- nested correlated sublink +SELECT (SELECT (SELECT user_id)) +FROM events_table e +ORDER BY 1 LIMIT 1; + +-- sublink with record type +SELECT (SELECT u FROM users_table u WHERE u.user_id = e.user_id AND time = 'Thu Nov 23 09:26:42.145043 2017') +FROM events_table e +GROUP BY 1 +ORDER BY 1 LIMIT 3; + +-- sublink with anonymous record type +SELECT (SELECT (user_id,value_1) FROM users_table u WHERE u.user_id = e.user_id AND time = 'Thu Nov 23 09:26:42.145043 2017') +FROM events_table e +WHERE user_id < 3 +GROUP BY 1 +ORDER BY 1 LIMIT 3; + +-- complex query using row_to_json +SELECT coalesce(json_agg(root ORDER BY user_id), '[]') AS root +FROM + (SELECT row_to_json( + (SELECT _1_e + FROM + (SELECT "_0_root.base".user_id AS user_id) AS _1_e)) AS root, user_id + FROM + (SELECT DISTINCT user_id FROM public.users_table ORDER BY 1) AS "_0_root.base") AS _2_root ; + +SELECT * +FROM + (SELECT + row_to_json((SELECT _1_e FROM (SELECT user_id) AS _1_e)) AS root, user_id + FROM + (SELECT DISTINCT user_id FROM public.users_table ORDER BY 1) as bar) AS foo ORDER BY user_id; + +-- non-colocated subquery join +SELECT count(*) FROM + + (SELECT event_type, (SELECT e.value_2 FROM users_reference_table WHERE user_id = 1 AND value_1 = 1 AND value_2 = 1), (SELECT e.value_2) + FROM events_table e) as foo + JOIN + (SELECT event_type, (SELECT e.value_2 FROM users_reference_table WHERE user_id = 5 AND value_1 = 1 AND value_2 = 1), (SELECT e.value_2) + FROM events_table e) as bar + ON bar.event_type = foo.event_type; + +-- subquery in the target list in HAVING should be fine +SELECT + user_id, count(*) +FROM + events_table e1 +GROUP BY user_id + HAVING + count(*) > (SELECT count(*) FROM (SELECT + (SELECT sum(user_id) FROM users_table WHERE user_id = u1.user_id GROUP BY user_id) + FROM users_table u1 + GROUP BY user_id) as foo) ORDER BY 1 DESC; + +-- make sure that we don't pushdown subqueries in the target list if no FROM clause +SELECT (SELECT DISTINCT user_id FROM users_table WHERE user_id = (SELECT max(user_id) FROM users_table )); + +-- not meaningful SELECT FOR UPDATE query that should fail +SELECT count(*) FROM (SELECT + (SELECT user_id FROM users_table WHERE user_id = u1.user_id FOR UPDATE) +FROM users_table u1 +GROUP BY user_id) as foo; + +DROP SCHEMA subquery_in_targetlist CASCADE; diff --git a/src/test/regress/sql/with_basics.sql b/src/test/regress/sql/with_basics.sql index fb7a857cf..6c7d9f381 100644 --- a/src/test/regress/sql/with_basics.sql +++ b/src/test/regress/sql/with_basics.sql @@ -62,19 +62,21 @@ SELECT user_id FROM ( SELECT user_id FROM cte WHERE value_2 > 0 ) a ORDER BY 1 LIMIT 3; --- CTE outside of FROM/WHERE errors out +-- CTE outside of FROM/WHERE errors WITH cte AS ( SELECT user_id FROM users_table WHERE value_2 IN (1, 2) ) SELECT (SELECT * FROM cte); WITH cte_basic AS ( - SELECT user_id FROM users_table WHERE user_id = 1 + SELECT user_id FROM users_table WHERE user_id = 1 LIMIT 1 ) SELECT (SELECT user_id FROM cte_basic), user_id FROM - users_table; + users_table +ORDER BY 1,2 +LIMIT 1; -- single-row sublink is acceptable when there is no FROM WITH cte AS (