diff --git a/src/ast/ddl.rs b/src/ast/ddl.rs index fd481213..5b74e65b 100644 --- a/src/ast/ddl.rs +++ b/src/ast/ddl.rs @@ -19,7 +19,7 @@ //! (commonly referred to as Data Definition Language, or DDL) #[cfg(not(feature = "std"))] -use alloc::{boxed::Box, format, string::String, vec, vec::Vec}; +use alloc::{boxed::Box, format, string::String, vec::Vec}; use core::fmt::{self, Display, Write}; #[cfg(feature = "serde")] diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 6ddf3281..2e4898a3 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -2787,10 +2787,11 @@ impl fmt::Display for Declare { } /// Sql options of a `CREATE TABLE` statement. -#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] +#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Default)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum CreateTableOptions { + #[default] None, /// Options specified using the `WITH` keyword. /// e.g. `WITH (description = "123")` @@ -2819,12 +2820,6 @@ pub enum CreateTableOptions { TableProperties(Vec), } -impl Default for CreateTableOptions { - fn default() -> Self { - Self::None - } -} - impl fmt::Display for CreateTableOptions { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { diff --git a/src/dialect/snowflake.rs b/src/dialect/snowflake.rs index 4e91bf8d..91d04175 100644 --- a/src/dialect/snowflake.rs +++ b/src/dialect/snowflake.rs @@ -1079,14 +1079,7 @@ pub fn parse_stage_name_identifier(parser: &mut Parser) -> Result { - return { - println!( - "Unexpected token {token:?} while parsing stage name identifier {ident:?}" - ); - parser.expected("stage name identifier", parser.peek_token()) - } - } + _ => return parser.expected("stage name identifier", parser.peek_token()), } } Ok(Ident::new(ident)) diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 90c52bb8..6225681f 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -4031,13 +4031,13 @@ impl<'a> Parser<'a> { /// See [`Self::peek_token`] for an example. pub fn peek_tokens_with_location(&self) -> [TokenWithSpan; N] { let mut index = self.index; - core::array::from_fn(|_| loop { + core::array::from_fn(|_| { let token = self.tokens.get(index); index += 1; - break token.cloned().unwrap_or(TokenWithSpan { + token.cloned().unwrap_or(TokenWithSpan { token: Token::EOF, span: Span::empty(), - }); + }) }) } @@ -4047,10 +4047,10 @@ impl<'a> Parser<'a> { /// See [`Self::peek_tokens`] for an example. pub fn peek_tokens_ref(&self) -> [&TokenWithSpan; N] { let mut index = self.index; - core::array::from_fn(|_| loop { + core::array::from_fn(|_| { let token = self.tokens.get(index); index += 1; - break token.unwrap_or(&EOF_TOKEN); + token.unwrap_or(&EOF_TOKEN) }) } @@ -8546,7 +8546,7 @@ impl<'a> Parser<'a> { return self.expected( "FULLTEXT or SPATIAL option without constraint name", TokenWithSpan { - token: Token::make_keyword(&name.to_string()), + token: Token::make_keyword(name.to_string()), span: next_token.span, }, ); @@ -11125,9 +11125,9 @@ impl<'a> Parser<'a> { let mut parts = vec![]; if dialect_of!(self is BigQueryDialect) && in_table_clause { loop { - let (ident, end_with_period) = self.parse_unquoted_hyphenated_identifier()?; + let ident = self.parse_identifier()?; parts.push(ObjectNamePart::Identifier(ident)); - if !self.consume_token(&Token::Period) && !end_with_period { + if !self.consume_token(&Token::Period) { break; } } @@ -11141,9 +11141,9 @@ impl<'a> Parser<'a> { span, })); } else if dialect_of!(self is BigQueryDialect) && in_table_clause { - let (ident, end_with_period) = self.parse_unquoted_hyphenated_identifier()?; + let ident = self.parse_identifier()?; parts.push(ObjectNamePart::Identifier(ident)); - if !self.consume_token(&Token::Period) && !end_with_period { + if !self.consume_token(&Token::Period) { break; } } else if self.dialect.supports_object_name_double_dot_notation() @@ -11322,85 +11322,6 @@ impl<'a> Parser<'a> { } } - /// On BigQuery, hyphens are permitted in unquoted identifiers inside of a FROM or - /// TABLE clause. - /// - /// The first segment must be an ordinary unquoted identifier, e.g. it must not start - /// with a digit. Subsequent segments are either must either be valid identifiers or - /// integers, e.g. foo-123 is allowed, but foo-123a is not. - /// - /// [BigQuery-lexical](https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical) - /// - /// Return a tuple of the identifier and a boolean indicating it ends with a period. - fn parse_unquoted_hyphenated_identifier(&mut self) -> Result<(Ident, bool), ParserError> { - match self.peek_token().token { - // Token::Word(w) => { - // let quote_style_is_none = w.quote_style.is_none(); - // let mut requires_whitespace = false; - // let mut ident = w.into_ident(self.next_token().span); - // if quote_style_is_none { - // while matches!(self.peek_token().token, Token::Minus) { - // unreachable!("Something went wrong in the tokenizer!"); - // // self.next_token(); - // // ident.value.push('-'); - - // // let token = self - // // .next_token_no_skip() - // // .cloned() - // // .unwrap_or(TokenWithSpan::wrap(Token::EOF)); - // // requires_whitespace = match token.token { - // // Token::Word(next_word) if next_word.quote_style.is_none() => { - // // ident.value.push_str(&next_word.value); - // // false - // // } - // // Token::Number(s, false) => { - // // // A number token can represent a decimal value ending with a period, e.g., `Number('123.')`. - // // // However, for an [ObjectName], it is part of a hyphenated identifier, e.g., `foo-123.bar`. - // // // - // // // If a number token is followed by a period, it is part of an [ObjectName]. - // // // Return the identifier with `true` if the number token is followed by a period, indicating that - // // // parsing should continue for the next part of the hyphenated identifier. - // // if s.ends_with('.') { - // // let Some(s) = s.split('.').next().filter(|s| { - // // !s.is_empty() && s.chars().all(|c| c.is_ascii_digit()) - // // }) else { - // // return self.expected( - // // "continuation of hyphenated identifier", - // // TokenWithSpan::new(Token::Number(s, false), token.span), - // // ); - // // }; - // // ident.value.push_str(s); - // // return Ok((ident, true)); - // // } else { - // // ident.value.push_str(&s); - // // } - // // // If next token is period, then it is part of an ObjectName and we don't expect whitespace - // // // after the number. - // // !matches!(self.peek_token().token, Token::Period) - // // } - // // _ => { - // // return self - // // .expected("continuation of hyphenated identifier", token); - // // } - // // } - // } - - // // If the last segment was a number, we must check that it's followed by whitespace, - // // otherwise foo-123a will be parsed as `foo-123` with the alias `a`. - // if requires_whitespace { - // let token = self.next_token(); - // if !matches!(token.token, Token::EOF) { - // return self - // .expected("whitespace following hyphenated identifier", token); - // } - // } - // } - // Ok((ident, false)) - // } - _ => Ok((self.parse_identifier()?, false)), - } - } - /// Parses a parenthesized, comma-separated list of column definitions within a view. fn parse_view_columns(&mut self) -> Result, ParserError> { if self.consume_token(&Token::LParen) { diff --git a/src/test_utils.rs b/src/test_utils.rs index 978447d9..a8c8afd5 100644 --- a/src/test_utils.rs +++ b/src/test_utils.rs @@ -154,7 +154,6 @@ impl TestedDialects { /// /// For multiple statements, use [`statements_parse_to`]. pub fn one_statement_parses_to(&self, sql: &str, canonical: &str) -> Statement { - println!("Testing SQL: {}", sql); let mut statements = self.parse_sql_statements(sql).expect(sql); assert_eq!(statements.len(), 1); if !canonical.is_empty() && sql != canonical { diff --git a/src/tokenizer.rs b/src/tokenizer.rs index 3fa46a48..b5d7a67f 100644 --- a/src/tokenizer.rs +++ b/src/tokenizer.rs @@ -23,7 +23,6 @@ #[cfg(not(feature = "std"))] use alloc::{ - borrow::ToOwned, format, string::{String, ToString}, vec, @@ -1319,12 +1318,12 @@ impl<'a> Tokenizer<'a> { // If so, what follows is definitely not part of a decimal number and // we should yield the dot as a dedicated token so compound identifiers // starting with digits can be parsed correctly. - if s == "." && self.dialect.supports_numeric_prefix() { - if !preceded_by_whitespace - && !matches!(prev_token, Some(Token::Plus | Token::Minus)) - { - return Ok(Some(Token::Period)); - } + if s == "." + && self.dialect.supports_numeric_prefix() + && !preceded_by_whitespace + && !matches!(prev_token, Some(Token::Plus | Token::Minus)) + { + return Ok(Some(Token::Period)); } // Consume fractional digits.