Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions datafusion/sql/src/unparser/plan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,15 @@ impl Unparser<'_> {
unproject_agg_exprs(filter.predicate.clone(), agg, None)?;
let filter_expr = self.expr_to_sql(&unprojected)?;
select.having(Some(filter_expr));
} else if let Some(window) = find_window_nodes_within_select(
plan,
None,
select.already_projected(),
) {
let unprojected =
unproject_window_exprs(filter.predicate.clone(), &window)?;
let filter_expr = self.expr_to_sql(&unprojected)?;
select.qualify(Some(filter_expr));
} else {
let filter_expr = self.expr_to_sql(&filter.predicate)?;
select.selection(Some(filter_expr));
Expand Down
42 changes: 42 additions & 0 deletions datafusion/sql/tests/cases/plan_to_sql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,14 @@ use datafusion_common::{
assert_contains, Column, DFSchema, DFSchemaRef, DataFusionError, Result,
TableReference,
};
use datafusion_expr::expr::{WindowFunction, WindowFunctionParams};
use datafusion_expr::test::function_stub::{
count_udaf, max_udaf, min_udaf, sum, sum_udaf,
};
use datafusion_expr::{
cast, col, lit, table_scan, wildcard, EmptyRelation, Expr, Extension, LogicalPlan,
LogicalPlanBuilder, Union, UserDefinedLogicalNode, UserDefinedLogicalNodeCore,
WindowFrame, WindowFunctionDefinition,
};
use datafusion_functions::unicode;
use datafusion_functions_aggregate::grouping::grouping_udaf;
Expand Down Expand Up @@ -2519,6 +2521,46 @@ fn test_unparse_left_semi_join_with_table_scan_projection() -> Result<()> {
Ok(())
}

#[test]
fn test_unparse_window() -> Result<()> {
// SubqueryAlias: t
// Projection: t.k, t.v, rank() PARTITION BY [t.k] ORDER BY [t.v ASC NULLS LAST] RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW AS r
// Filter: rank() PARTITION BY [t.k] ORDER BY [t.v ASC NULLS LAST] RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW = UInt64(1)
// WindowAggr: windowExpr=[[rank() PARTITION BY [t.k] ORDER BY [t.v ASC NULLS LAST] RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW]]
// TableScan: t projection=[k, v]

let schema = Schema::new(vec![
Field::new("k", DataType::Int32, false),
Field::new("v", DataType::Int32, false),
]);
let window_expr = Expr::WindowFunction(Box::new(WindowFunction {
fun: WindowFunctionDefinition::WindowUDF(rank_udwf()),
params: WindowFunctionParams {
args: vec![],
partition_by: vec![col("k")],
order_by: vec![col("v").sort(true, true)],
window_frame: WindowFrame::new(None),
null_treatment: None,
distinct: false,
},
}));
let table_scan = table_scan(Some("test"), &schema, Some(vec![0, 1]))?.build()?;
let plan = LogicalPlanBuilder::window_plan(table_scan, vec![window_expr])?;

let name = plan.schema().fields().last().unwrap().name().clone();
let plan = LogicalPlanBuilder::from(plan)
.filter(col(name.clone()).eq(lit(1i64)))?
.project(vec![col("k"), col("v"), col(name)])?
.build()?;
let unparser = Unparser::new(&UnparserPostgreSqlDialect {});
let sql = unparser.plan_to_sql(&plan)?;
assert_snapshot!(
sql,
@r#"SELECT "test"."k", "test"."v", rank() OVER (PARTITION BY "test"."k" ORDER BY "test"."v" ASC NULLS FIRST ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) FROM "test" QUALIFY (rank() OVER (PARTITION BY "test"."k" ORDER BY "test"."v" ASC NULLS FIRST ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) = 1)"#

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @chenkovsky, this now generates valid Datafusion SQL.
Unfortunately, the QUALIFY keyword is not available in PostgreSQL, as well as other systems (https://modern-sql.com/caniuse/qualify), meaning the output does not work there.

);
Ok(())
}

#[test]
fn test_like_filter() {
let statement = generate_round_trip_statement(
Expand Down