diff --git a/src/backend/distributed/planner/multi_physical_planner.c b/src/backend/distributed/planner/multi_physical_planner.c index bb104c998..f27097913 100644 --- a/src/backend/distributed/planner/multi_physical_planner.c +++ b/src/backend/distributed/planner/multi_physical_planner.c @@ -106,6 +106,8 @@ static RangeTblEntry * DerivedRangeTableEntry(MultiNode *multiNode, List *column List *tableIdList); static List * DerivedColumnNameList(uint32 columnCount, uint64 generatingJobId); static Query * BuildSubqueryJobQuery(MultiNode *multiNode); +static void UpdateAllColumnAttributes(Node *columnContainer, List *rangeTableList, + List *dependedJobList); static void UpdateColumnAttributes(Var *column, List *rangeTableList, List *dependedJobList); static Index NewTableId(Index originalTableId, List *rangeTableList); @@ -579,10 +581,8 @@ BuildJobQuery(MultiNode *multiNode, List *dependedJobList) List *sortClauseList = NIL; List *groupClauseList = NIL; List *selectClauseList = NIL; - List *columnList = NIL; Node *limitCount = NULL; Node *limitOffset = NULL; - ListCell *columnCell = NULL; FromExpr *joinTree = NULL; Node *joinRoot = NULL; Node *havingQual = NULL; @@ -650,13 +650,7 @@ BuildJobQuery(MultiNode *multiNode, List *dependedJobList) /* update the column attributes for target entries */ if (updateColumnAttributes) { - ListCell *columnCell = NULL; - List *columnList = pull_var_clause_default((Node *) targetList); - foreach(columnCell, columnList) - { - Var *column = (Var *) lfirst(columnCell); - UpdateColumnAttributes(column, rangeTableList, dependedJobList); - } + UpdateAllColumnAttributes((Node *) targetList, rangeTableList, dependedJobList); } /* extract limit count/offset and sort clauses */ @@ -676,16 +670,12 @@ BuildJobQuery(MultiNode *multiNode, List *dependedJobList) /* build the where clause list using select predicates */ selectClauseList = QuerySelectClauseList(multiNode); - /* set correct column attributes for select columns */ + /* set correct column attributes for select and having clauses */ if (updateColumnAttributes) { - columnCell = NULL; - columnList = pull_var_clause_default((Node *) selectClauseList); - foreach(columnCell, columnList) - { - Var *column = (Var *) lfirst(columnCell); - UpdateColumnAttributes(column, rangeTableList, dependedJobList); - } + UpdateAllColumnAttributes((Node *) selectClauseList, rangeTableList, + dependedJobList); + UpdateAllColumnAttributes(havingQual, rangeTableList, dependedJobList); } /* @@ -1526,6 +1516,25 @@ BuildSubqueryJobQuery(MultiNode *multiNode) } +/* + * UpdateAllColumnAttributes extracts column references from provided columnContainer + * and calls UpdateColumnAttributes to updates the column's range table reference (varno) and + * column attribute number for the range table (varattno). + */ +static void +UpdateAllColumnAttributes(Node *columnContainer, List *rangeTableList, + List *dependedJobList) +{ + ListCell *columnCell = NULL; + List *columnList = pull_var_clause_default(columnContainer); + foreach(columnCell, columnList) + { + Var *column = (Var *) lfirst(columnCell); + UpdateColumnAttributes(column, rangeTableList, dependedJobList); + } +} + + /* * UpdateColumnAttributes updates the column's range table reference (varno) and * column attribute number for the range table (varattno). The function uses the diff --git a/src/test/regress/expected/multi_view.out b/src/test/regress/expected/multi_view.out index e467a8900..9eb7e779f 100644 --- a/src/test/regress/expected/multi_view.out +++ b/src/test/regress/expected/multi_view.out @@ -428,8 +428,8 @@ ORDER BY 2 DESC, 1; 5 | 14 (3 rows) --- non-partition key joins are not supported inside subquery --- since the join with a table +-- non-partition key joins are supported inside subquery +-- via pull-push execution SELECT * FROM (SELECT ru.user_id, count(*) FROM recent_users ru @@ -438,7 +438,13 @@ SELECT * FROM GROUP BY ru.user_id ORDER BY 2 DESC, 1) s1 ORDER BY 2 DESC, 1; -ERROR: bogus varno: 3 + user_id | count +---------+------- + 1 | 24 + 3 | 23 + 5 | 7 +(3 rows) + -- join between views -- recent users who has an event in recent events SELECT ru.user_id FROM recent_users ru JOIN recent_events re USING(user_id) GROUP BY ru.user_id ORDER BY ru.user_id; @@ -533,7 +539,8 @@ SELECT * FROM ON(ru.user_id = et.event_type) ) s1 ORDER BY 2 DESC, 1; -ERROR: bogus varno: 3 +ERROR: cannot pushdown the subquery +DETAIL: Complex subqueries and CTEs cannot be in the outer part of the outer join -- create a select only view CREATE VIEW selected_users AS SELECT * FROM users_table WHERE value_1 >= 1 and value_1 <3; CREATE VIEW recent_selected_users AS SELECT su.* FROM selected_users su JOIN recent_users ru USING(user_id); @@ -863,7 +870,7 @@ EXPLAIN (COSTS FALSE) SELECT et.* FROM recent_10_users JOIN events_table et USIN -> Sort Sort Key: remote_scan."time" DESC -> Custom Scan (Citus Real-Time) - -> Distributed Subplan 95_1 + -> Distributed Subplan 96_1 -> Limit -> Sort Sort Key: max((max(remote_scan.lastseen))) DESC diff --git a/src/test/regress/expected/multi_view_0.out b/src/test/regress/expected/multi_view_0.out index 136dc35ea..f96dd5489 100644 --- a/src/test/regress/expected/multi_view_0.out +++ b/src/test/regress/expected/multi_view_0.out @@ -428,8 +428,8 @@ ORDER BY 2 DESC, 1; 5 | 14 (3 rows) --- non-partition key joins are not supported inside subquery --- since the join with a table +-- non-partition key joins are supported inside subquery +-- via pull-push execution SELECT * FROM (SELECT ru.user_id, count(*) FROM recent_users ru @@ -438,7 +438,13 @@ SELECT * FROM GROUP BY ru.user_id ORDER BY 2 DESC, 1) s1 ORDER BY 2 DESC, 1; -ERROR: bogus varno: 3 + user_id | count +---------+------- + 1 | 24 + 3 | 23 + 5 | 7 +(3 rows) + -- join between views -- recent users who has an event in recent events SELECT ru.user_id FROM recent_users ru JOIN recent_events re USING(user_id) GROUP BY ru.user_id ORDER BY ru.user_id; @@ -533,7 +539,8 @@ SELECT * FROM ON(ru.user_id = et.event_type) ) s1 ORDER BY 2 DESC, 1; -ERROR: bogus varno: 3 +ERROR: cannot pushdown the subquery +DETAIL: Complex subqueries and CTEs cannot be in the outer part of the outer join -- create a select only view CREATE VIEW selected_users AS SELECT * FROM users_table WHERE value_1 >= 1 and value_1 <3; CREATE VIEW recent_selected_users AS SELECT su.* FROM selected_users su JOIN recent_users ru USING(user_id); @@ -865,7 +872,7 @@ EXPLAIN (COSTS FALSE) SELECT et.* FROM recent_10_users JOIN events_table et USIN -> Sort Sort Key: remote_scan."time" DESC -> Custom Scan (Citus Real-Time) - -> Distributed Subplan 95_1 + -> Distributed Subplan 96_1 -> Limit -> Sort Sort Key: max((max(remote_scan.lastseen))) DESC diff --git a/src/test/regress/sql/multi_view.sql b/src/test/regress/sql/multi_view.sql index 5f2f2ef1f..d131e149d 100644 --- a/src/test/regress/sql/multi_view.sql +++ b/src/test/regress/sql/multi_view.sql @@ -220,8 +220,8 @@ SELECT * FROM ORDER BY 2 DESC, 1) s1 ORDER BY 2 DESC, 1; --- non-partition key joins are not supported inside subquery --- since the join with a table +-- non-partition key joins are supported inside subquery +-- via pull-push execution SELECT * FROM (SELECT ru.user_id, count(*) FROM recent_users ru