Rewrite Filter plans that have a Window as their input by inserting a SubqueryAlias. When a Filter directly operates on a Window plan, it can cause issues during SQL unparsing because window functions in a WHERE clause are not valid SQL. The solution is to wrap the Window plan in a SubqueryAlias, effectively creating a derived table. Example transformation: Filter: condition Window: window_func
(plan: LogicalPlan)
| 120 | /// Window: window_function |
| 121 | /// TableScan: table |
| 122 | pub(super) fn rewrite_qualify(plan: LogicalPlan) -> Result<LogicalPlan> { |
| 123 | let transformed_plan = plan.transform_up(|plan| match plan { |
| 124 | // Check if the filter's input is a Window plan |
| 125 | LogicalPlan::Filter(mut filter) => { |
| 126 | if matches!(&*filter.input, LogicalPlan::Window(_)) { |
| 127 | // Create a SubqueryAlias around the Window plan |
| 128 | let qualifier = filter |
| 129 | .input |
| 130 | .schema() |
| 131 | .iter() |
| 132 | .find_map(|(q, _)| q) |
| 133 | .map(|q| q.to_string()) |
| 134 | .unwrap_or_else(|| "__qualify_subquery".to_string()); |
| 135 | |
| 136 | // for Postgres, name of column for 'rank() over (...)' is 'rank' |
| 137 | // but in Datafusion, it is 'rank() over (...)' |
| 138 | // without projection, it's still an invalid sql in Postgres |
| 139 | |
| 140 | let project_exprs = filter |
| 141 | .input |
| 142 | .schema() |
| 143 | .iter() |
| 144 | .map(|(_, f)| datafusion_expr::col(f.name()).alias(f.name())) |
| 145 | .collect::<Vec<_>>(); |
| 146 | |
| 147 | let input = |
| 148 | datafusion_expr::LogicalPlanBuilder::from(Arc::clone(&filter.input)) |
| 149 | .project(project_exprs)? |
| 150 | .build()?; |
| 151 | |
| 152 | let subquery_alias = |
| 153 | datafusion_expr::SubqueryAlias::try_new(Arc::new(input), qualifier)?; |
| 154 | |
| 155 | filter.input = Arc::new(LogicalPlan::SubqueryAlias(subquery_alias)); |
| 156 | Ok(Transformed::yes(LogicalPlan::Filter(filter))) |
| 157 | } else { |
| 158 | Ok(Transformed::no(LogicalPlan::Filter(filter))) |
| 159 | } |
| 160 | } |
| 161 | |
| 162 | _ => Ok(Transformed::no(plan)), |
| 163 | }); |
| 164 | |
| 165 | transformed_plan.data() |
| 166 | } |
| 167 | |
| 168 | /// Rewrite logic plan for query that order by columns are not in projections |
| 169 | /// Plan before rewrite: |
no test coverage detected
searching dependent graphs…