diff --git a/src/parser/mod.rs b/src/parser/mod.rs index db54296fce..0ed1b2f4b9 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -20848,7 +20848,16 @@ impl<'a> Parser<'a> { /// Parse a window specification. pub fn parse_window_spec(&mut self) -> Result { let window_name = match &self.peek_token_ref().token { - Token::Word(word) if word.keyword == Keyword::NoKeyword => { + Token::Word(w) + if !matches!( + w.keyword, + Keyword::PARTITION + | Keyword::ORDER + | Keyword::ROWS + | Keyword::RANGE + | Keyword::GROUPS + ) => + { self.parse_optional_ident()? } _ => None, diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs index 025c2cf207..ff2df7ce49 100644 --- a/tests/sqlparser_common.rs +++ b/tests/sqlparser_common.rs @@ -20803,3 +20803,24 @@ fn display_nested_unary_minus_in_linear_time() { .expect("display should not take exponential time"); assert_eq!(printed, sql); } + +#[test] +fn parse_window_spec_keyword_base_window_name() { + let dialects = all_dialects(); + for name in ["w", "id", "part"] { + let sql = format!("SELECT count(*) OVER ({name} ORDER BY a) FROM t"); + let select = dialects.verified_only_select(&sql); + match expr_from_projection(&select.projection[0]) { + Expr::Function(Function { + over: Some(WindowType::WindowSpec(spec)), + .. + }) => assert_eq!(spec.window_name, Some(Ident::new(name)), "{sql}"), + other => panic!("{sql}: unexpected {other:?}"), + } + } + dialects.verified_stmt("SELECT count(*) OVER (ORDER BY a) FROM t"); + dialects.verified_stmt("SELECT count(*) OVER (PARTITION BY a) FROM t"); + dialects.verified_stmt( + "SELECT count(*) OVER (ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM t", + ); +}