From 59f27eb53c27a2988fc973f34d014d07e0d05588 Mon Sep 17 00:00:00 2001 From: wugeer <1284057728@qq.com> Date: Thu, 18 Jun 2026 18:23:26 +0800 Subject: [PATCH 1/3] fix merge conflict --- src/ast/mod.rs | 56 +++++++++++++++++++++++++++++++++++++-- src/parser/mod.rs | 35 ++++++++++++++++++------ tests/sqlparser_common.rs | 8 ++++++ tests/sqlparser_hive.rs | 7 +++++ tests/sqlparser_sqlite.rs | 2 ++ 5 files changed, 98 insertions(+), 10 deletions(-) diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 9dad8470f..2ede3e25a 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -2269,12 +2269,58 @@ pub struct WindowSpec { pub window_name: Option, /// `OVER (PARTITION BY ...)` pub partition_by: Vec, + /// The kind of partitioning clause used in the window specification. + pub partition_by_kind: WindowPartitionByKind, /// `OVER (ORDER BY ...)` pub order_by: Vec, + /// The kind of ordering clause used in the window specification. + pub order_by_kind: WindowOrderByKind, /// `OVER (window frame)` pub window_frame: Option, } +/// The kind of partitioning clause in a window specification. +#[derive(Debug, Default, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +pub enum WindowPartitionByKind { + /// `PARTITION BY` + #[default] + Partition, + /// Hive `DISTRIBUTE BY` + Distribute, +} + +impl fmt::Display for WindowPartitionByKind { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_str(match self { + Self::Partition => "PARTITION BY", + Self::Distribute => "DISTRIBUTE BY", + }) + } +} + +/// The kind of ordering clause in a window specification. +#[derive(Debug, Default, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +pub enum WindowOrderByKind { + /// `ORDER BY` + #[default] + Order, + /// Hive `SORT BY` + Sort, +} + +impl fmt::Display for WindowOrderByKind { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_str(match self { + Self::Order => "ORDER BY", + Self::Sort => "SORT BY", + }) + } +} + impl fmt::Display for WindowSpec { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut is_first = true; @@ -2292,7 +2338,8 @@ impl fmt::Display for WindowSpec { is_first = false; write!( f, - "PARTITION BY {}", + "{} {}", + self.partition_by_kind, display_comma_separated(&self.partition_by) )?; } @@ -2301,7 +2348,12 @@ impl fmt::Display for WindowSpec { SpaceOrNewline.fmt(f)?; } is_first = false; - write!(f, "ORDER BY {}", display_comma_separated(&self.order_by))?; + write!( + f, + "{} {}", + self.order_by_kind, + display_comma_separated(&self.order_by) + )?; } if let Some(window_frame) = &self.window_frame { if !is_first { diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 6540cdc0d..49cdfd0ff 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -20272,15 +20272,32 @@ impl<'a> Parser<'a> { _ => None, }; - let partition_by = if self.parse_keywords(&[Keyword::PARTITION, Keyword::BY]) { - self.parse_comma_separated(Parser::parse_expr)? - } else { - vec![] - }; - let order_by = if self.parse_keywords(&[Keyword::ORDER, Keyword::BY]) { - self.parse_comma_separated(Parser::parse_order_by_expr)? + let (partition_by_kind, partition_by) = + if self.parse_keywords(&[Keyword::PARTITION, Keyword::BY]) { + ( + WindowPartitionByKind::Partition, + self.parse_comma_separated(Parser::parse_expr)?, + ) + } else if self.parse_keywords(&[Keyword::DISTRIBUTE, Keyword::BY]) { + ( + WindowPartitionByKind::Distribute, + self.parse_comma_separated(Parser::parse_expr)?, + ) + } else { + (WindowPartitionByKind::Partition, vec![]) + }; + let (order_by_kind, order_by) = if self.parse_keywords(&[Keyword::ORDER, Keyword::BY]) { + ( + WindowOrderByKind::Order, + self.parse_comma_separated(Parser::parse_order_by_expr)?, + ) + } else if self.parse_keywords(&[Keyword::SORT, Keyword::BY]) { + ( + WindowOrderByKind::Sort, + self.parse_comma_separated(Parser::parse_order_by_expr)?, + ) } else { - vec![] + (WindowOrderByKind::Order, vec![]) }; let window_frame = if !self.consume_token(&Token::RParen) { @@ -20293,7 +20310,9 @@ impl<'a> Parser<'a> { Ok(WindowSpec { window_name, partition_by, + partition_by_kind, order_by, + order_by_kind, window_frame, }) } diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs index be3026f63..5a32f91c6 100644 --- a/tests/sqlparser_common.rs +++ b/tests/sqlparser_common.rs @@ -3095,6 +3095,7 @@ fn parse_select_qualify() { over: Some(WindowType::WindowSpec(WindowSpec { window_name: None, partition_by: vec![Expr::Identifier(Ident::new("p"))], + partition_by_kind: WindowPartitionByKind::Partition, order_by: vec![OrderByExpr { expr: Expr::Identifier(Ident::new("o")), options: OrderByOptions { @@ -3103,6 +3104,7 @@ fn parse_select_qualify() { }, with_fill: None, }], + order_by_kind: WindowOrderByKind::Order, window_frame: None, })), within_group: vec![] @@ -5815,6 +5817,7 @@ fn parse_window_functions() { over: Some(WindowType::WindowSpec(WindowSpec { window_name: None, partition_by: vec![], + partition_by_kind: WindowPartitionByKind::Partition, order_by: vec![OrderByExpr { expr: Expr::Identifier(Ident::new("dt")), options: OrderByOptions { @@ -5823,6 +5826,7 @@ fn parse_window_functions() { }, with_fill: None, }], + order_by_kind: WindowOrderByKind::Order, window_frame: None, })), within_group: vec![], @@ -6037,6 +6041,7 @@ fn test_parse_named_window() { NamedWindowExpr::WindowSpec(WindowSpec { window_name: None, partition_by: vec![], + partition_by_kind: WindowPartitionByKind::Partition, order_by: vec![OrderByExpr { expr: Expr::Identifier(Ident { value: "C12".to_string(), @@ -6049,6 +6054,7 @@ fn test_parse_named_window() { }, with_fill: None, }], + order_by_kind: WindowOrderByKind::Order, window_frame: None, }), ), @@ -6065,7 +6071,9 @@ fn test_parse_named_window() { quote_style: None, span: Span::empty(), })], + partition_by_kind: WindowPartitionByKind::Partition, order_by: vec![], + order_by_kind: WindowOrderByKind::Order, window_frame: None, }), ), diff --git a/tests/sqlparser_hive.rs b/tests/sqlparser_hive.rs index 21e76e23b..6ad18fb87 100644 --- a/tests/sqlparser_hive.rs +++ b/tests/sqlparser_hive.rs @@ -569,6 +569,13 @@ fn parse_create_table_with_map_column_comment() { ); } +#[test] +fn parse_row_number_window_function() { + hive().verified_stmt( + "SELECT row_number() OVER (DISTRIBUTE BY age SORT BY update_time DESC) AS row_num FROM sdl.xxx", + ); +} + fn hive() -> TestedDialects { TestedDialects::new(vec![Box::new(HiveDialect {})]) } diff --git a/tests/sqlparser_sqlite.rs b/tests/sqlparser_sqlite.rs index 70c73bf76..e45d26c5e 100644 --- a/tests/sqlparser_sqlite.rs +++ b/tests/sqlparser_sqlite.rs @@ -439,7 +439,9 @@ fn parse_window_function_with_filter() { over: Some(WindowType::WindowSpec(WindowSpec { window_name: None, partition_by: vec![], + partition_by_kind: WindowPartitionByKind::Partition, order_by: vec![], + order_by_kind: WindowOrderByKind::Order, window_frame: None, })), filter: Some(Box::new(Expr::Identifier(Ident::new("y")))), From c7fb3f6ae37764cfd2d08a0361412936c4e2796a Mon Sep 17 00:00:00 2001 From: wugeer <1284057728@qq.com> Date: Thu, 18 Jun 2026 18:13:29 +0800 Subject: [PATCH 2/3] remove `supports_window_spec_distribute_sort` func and redundant `default` attributes --- src/ast/mod.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 2ede3e25a..a534f6113 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -2280,12 +2280,11 @@ pub struct WindowSpec { } /// The kind of partitioning clause in a window specification. -#[derive(Debug, Default, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)] +#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum WindowPartitionByKind { /// `PARTITION BY` - #[default] Partition, /// Hive `DISTRIBUTE BY` Distribute, From 75d745786ba9a88968663f6875ce7334e5fb6fef Mon Sep 17 00:00:00 2001 From: wugeer <1284057728@qq.com> Date: Thu, 18 Jun 2026 18:30:34 +0800 Subject: [PATCH 3/3] remove redundant `default` attributes --- src/ast/mod.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/ast/mod.rs b/src/ast/mod.rs index a534f6113..7ed4e2daa 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -2300,12 +2300,11 @@ impl fmt::Display for WindowPartitionByKind { } /// The kind of ordering clause in a window specification. -#[derive(Debug, Default, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)] +#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum WindowOrderByKind { /// `ORDER BY` - #[default] Order, /// Hive `SORT BY` Sort,