(
expr: ExprOrSource,
window: rq::Window,
ctx: &mut Context,
span: Option<Span>,
)
| 808 | } |
| 809 | |
| 810 | fn translate_windowed( |
| 811 | expr: ExprOrSource, |
| 812 | window: rq::Window, |
| 813 | ctx: &mut Context, |
| 814 | span: Option<Span>, |
| 815 | ) -> Result<ExprOrSource> { |
| 816 | let default_frame = { |
| 817 | let (kind, range) = if window.sort.is_empty() { |
| 818 | (WindowKind::Rows, Range::unbounded()) |
| 819 | } else { |
| 820 | ( |
| 821 | WindowKind::Range, |
| 822 | Range { |
| 823 | start: None, |
| 824 | end: Some(rq::Expr { |
| 825 | kind: rq::ExprKind::Literal(Literal::Integer(0)), |
| 826 | span: None, |
| 827 | }), |
| 828 | }, |
| 829 | ) |
| 830 | }; |
| 831 | WindowFrame { kind, range } |
| 832 | }; |
| 833 | |
| 834 | let supports_frame = matches!( |
| 835 | expr, |
| 836 | ExprOrSource::Source(SourceExpr { |
| 837 | window_frame: true, |
| 838 | .. |
| 839 | }) |
| 840 | ); |
| 841 | |
| 842 | let mut order_by: Vec<OrderByExpr> = (window.sort) |
| 843 | .into_iter() |
| 844 | .map(|sort| translate_column_sort(&sort, ctx)) |
| 845 | .try_collect()?; |
| 846 | |
| 847 | // Some dialects (e.g., Snowflake) require ORDER BY for window functions |
| 848 | // When no ORDER BY is specified, use ORDER BY 1 as a fallback |
| 849 | if order_by.is_empty() && ctx.dialect.requires_order_by_in_window_function() { |
| 850 | order_by.push(OrderByExpr { |
| 851 | expr: sql_ast::Expr::Value(Value::Number("1".to_string(), false).into()), |
| 852 | options: sqlparser::ast::OrderByOptions { |
| 853 | asc: None, |
| 854 | nulls_first: None, |
| 855 | }, |
| 856 | with_fill: None, |
| 857 | }); |
| 858 | } |
| 859 | |
| 860 | let window = WindowSpec { |
| 861 | window_name: None, |
| 862 | partition_by: try_into_exprs(window.partition, ctx, span)?, |
| 863 | order_by, |
| 864 | window_frame: if supports_frame && window.frame != default_frame { |
| 865 | Some(try_into_window_frame(window.frame)?) |
| 866 | } else { |
| 867 | None |
no test coverage detected