MCPcopy Create free account
hub / github.com/apache/datafusion / rewrite_qualify

Function rewrite_qualify

datafusion/sql/src/unparser/rewrite.rs:122–166  ·  view source on GitHub ↗

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)

Source from the content-addressed store, hash-verified

120/// Window: window_function
121/// TableScan: table
122pub(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:

Callers 1

plan_to_sqlMethod · 0.85

Calls 14

newFunction · 0.85
SubqueryAliasClass · 0.85
transform_upMethod · 0.80
colFunction · 0.50
FilterClass · 0.50
mapMethod · 0.45
iterMethod · 0.45
schemaMethod · 0.45
to_stringMethod · 0.45
aliasMethod · 0.45
nameMethod · 0.45
buildMethod · 0.45

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…