@@ -29,7 +29,7 @@ use crate::utils::{
29
29
30
30
use datafusion_common:: error:: DataFusionErrorBuilder ;
31
31
use datafusion_common:: tree_node:: { TreeNode , TreeNodeRecursion } ;
32
- use datafusion_common:: { not_impl_err, plan_err, DataFusionError , Result } ;
32
+ use datafusion_common:: { not_impl_err, plan_err, Result } ;
33
33
use datafusion_common:: { RecursionUnnestOption , UnnestOptions } ;
34
34
use datafusion_expr:: expr:: { Alias , PlannedReplaceSelectItem , WildcardOptions } ;
35
35
use datafusion_expr:: expr_rewriter:: {
@@ -85,7 +85,7 @@ impl<S: ContextProvider> SqlToRel<'_, S> {
85
85
86
86
// Handle named windows before processing the projection expression
87
87
check_conflicting_windows ( & select. named_window ) ?;
88
- match_window_definitions ( & mut select. projection , & select. named_window ) ?;
88
+ self . match_window_definitions ( & mut select. projection , & select. named_window ) ?;
89
89
// Process the SELECT expressions
90
90
let select_exprs = self . prepare_select_exprs (
91
91
& base_plan,
@@ -868,42 +868,34 @@ impl<S: ContextProvider> SqlToRel<'_, S> {
868
868
869
869
Ok ( ( plan, select_exprs_post_aggr, having_expr_post_aggr) )
870
870
}
871
- }
872
-
873
- // If there are any multiple-defined windows, we raise an error.
874
- fn check_conflicting_windows ( window_defs : & [ NamedWindowDefinition ] ) -> Result < ( ) > {
875
- for ( i, window_def_i) in window_defs. iter ( ) . enumerate ( ) {
876
- for window_def_j in window_defs. iter ( ) . skip ( i + 1 ) {
877
- if window_def_i. 0 == window_def_j. 0 {
878
- return plan_err ! (
879
- "The window {} is defined multiple times!" ,
880
- window_def_i. 0
881
- ) ;
882
- }
883
- }
884
- }
885
- Ok ( ( ) )
886
- }
887
871
888
- // If the projection is done over a named window, that window
889
- // name must be defined. Otherwise, it gives an error.
890
- fn match_window_definitions (
891
- projection : & mut [ SelectItem ] ,
892
- named_windows : & [ NamedWindowDefinition ] ,
893
- ) -> Result < ( ) > {
894
- for proj in projection. iter_mut ( ) {
895
- if let SelectItem :: ExprWithAlias { expr, alias : _ }
896
- | SelectItem :: UnnamedExpr ( expr) = proj
897
- {
898
- let mut err = None ;
899
- visit_expressions_mut ( expr, |expr| {
900
- if let SQLExpr :: Function ( f) = expr {
901
- if let Some ( WindowType :: NamedWindow ( _) ) = & f. over {
902
- for NamedWindowDefinition ( window_ident, window_expr) in
903
- named_windows
904
- {
905
- if let Some ( WindowType :: NamedWindow ( ident) ) = & f. over {
906
- if ident. eq ( window_ident) {
872
+ // If the projection is done over a named window, that window
873
+ // name must be defined. Otherwise, it gives an error.
874
+ fn match_window_definitions (
875
+ & self ,
876
+ projection : & mut [ SelectItem ] ,
877
+ named_windows : & [ NamedWindowDefinition ] ,
878
+ ) -> Result < ( ) > {
879
+ let named_windows: Vec < ( & NamedWindowDefinition , String ) > = named_windows
880
+ . iter ( )
881
+ . map ( |w| ( w, self . ident_normalizer . normalize ( w. 0 . clone ( ) ) ) )
882
+ . collect ( ) ;
883
+ for proj in projection. iter_mut ( ) {
884
+ if let SelectItem :: ExprWithAlias { expr, alias : _ }
885
+ | SelectItem :: UnnamedExpr ( expr) = proj
886
+ {
887
+ let mut err = None ;
888
+ visit_expressions_mut ( expr, |expr| {
889
+ if let SQLExpr :: Function ( f) = expr {
890
+ if let Some ( WindowType :: NamedWindow ( ident) ) = & f. over {
891
+ let normalized_ident =
892
+ self . ident_normalizer . normalize ( ident. clone ( ) ) ;
893
+ for (
894
+ NamedWindowDefinition ( _, window_expr) ,
895
+ normalized_window_ident,
896
+ ) in named_windows. iter ( )
897
+ {
898
+ if normalized_ident. eq ( normalized_window_ident) {
907
899
f. over = Some ( match window_expr {
908
900
NamedWindowExpr :: NamedWindow ( ident) => {
909
901
WindowType :: NamedWindow ( ident. clone ( ) )
@@ -914,20 +906,34 @@ fn match_window_definitions(
914
906
} )
915
907
}
916
908
}
917
- }
918
- // All named windows must be defined with a WindowSpec.
919
- if let Some ( WindowType :: NamedWindow ( ident) ) = & f. over {
920
- err = Some ( DataFusionError :: Plan ( format ! (
921
- "The window {ident} is not defined!"
922
- ) ) ) ;
923
- return ControlFlow :: Break ( ( ) ) ;
909
+ // All named windows must be defined with a WindowSpec.
910
+ if let Some ( WindowType :: NamedWindow ( ident) ) = & f. over {
911
+ err =
912
+ Some ( plan_err ! ( "The window {ident} is not defined!" ) ) ;
913
+ return ControlFlow :: Break ( ( ) ) ;
914
+ }
924
915
}
925
916
}
917
+ ControlFlow :: Continue ( ( ) )
918
+ } ) ;
919
+ if let Some ( err) = err {
920
+ return err;
926
921
}
927
- ControlFlow :: Continue ( ( ) )
928
- } ) ;
929
- if let Some ( err) = err {
930
- return Err ( err) ;
922
+ }
923
+ }
924
+ Ok ( ( ) )
925
+ }
926
+ }
927
+
928
+ // If there are any multiple-defined windows, we raise an error.
929
+ fn check_conflicting_windows ( window_defs : & [ NamedWindowDefinition ] ) -> Result < ( ) > {
930
+ for ( i, window_def_i) in window_defs. iter ( ) . enumerate ( ) {
931
+ for window_def_j in window_defs. iter ( ) . skip ( i + 1 ) {
932
+ if window_def_i. 0 == window_def_j. 0 {
933
+ return plan_err ! (
934
+ "The window {} is defined multiple times!" ,
935
+ window_def_i. 0
936
+ ) ;
931
937
}
932
938
}
933
939
}
0 commit comments