diff --git a/src/ast/mod.rs b/src/ast/mod.rs index c19466ce0..a49a90a0b 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -17,7 +17,9 @@ use alloc::{ string::{String, ToString}, vec::Vec, }; +use core::borrow::Borrow; use core::fmt; +use std::ops::Deref; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; @@ -44,6 +46,7 @@ pub use self::value::{ escape_quoted_string, DateTimeField, DollarQuotedString, TrimWhereField, Value, }; +use crate::tokenizer::Span; #[cfg(feature = "visitor")] pub use visitor::*; @@ -251,6 +254,76 @@ impl fmt::Display for JsonOperator { } } +#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] +pub struct WithSpan +where + T: Clone + Eq + Ord + std::hash::Hash + PartialOrd + PartialEq, +{ + inner: T, + span: Span, +} + +impl WithSpan +where + T: Clone + Eq + Ord + std::hash::Hash + PartialOrd + PartialEq, +{ + pub fn new(inner: T, span: Span) -> Self { + Self { inner, span } + } + + pub fn unwrap(self) -> T { + self.inner + } +} + +pub trait SpanWrapped: Clone + Eq + Ord + std::hash::Hash + PartialOrd + PartialEq { + fn spanning>(self, span: U) -> WithSpan { + WithSpan::new(self, span.into()) + } + + fn empty_span(self) -> WithSpan { + self.spanning(Span::default()) + } +} + +impl SpanWrapped for T +where + T: Clone + Eq + Ord + std::hash::Hash + PartialOrd + PartialEq, +{ + fn spanning>(self, span: U) -> WithSpan { + WithSpan::new(self, span.into()) + } +} + +impl Deref for WithSpan +where + T: Clone + Eq + Ord + std::hash::Hash + PartialOrd + PartialEq, +{ + type Target = T; + + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +impl Borrow for WithSpan +where + T: Clone + Eq + Ord + std::hash::Hash + PartialOrd + PartialEq, +{ + fn borrow(&self) -> &T { + &self.inner + } +} + +impl fmt::Display for WithSpan +where + T: Clone + Eq + Ord + std::hash::Hash + PartialOrd + PartialEq, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.inner) + } +} + /// An SQL expression of any type. /// /// The parser does not distinguish between expressions of different types @@ -265,7 +338,7 @@ impl fmt::Display for JsonOperator { )] pub enum Expr { /// Identifier e.g. table name or column name - Identifier(Ident), + Identifier(WithSpan), /// Multi-part identifier, e.g. `table_alias.column` or `schema.table.col` CompoundIdentifier(Vec), /// JSON access (postgres) eg: data->'tags' @@ -4162,6 +4235,12 @@ impl fmt::Display for SearchModifier { mod tests { use super::*; + fn ident>(value: T) -> WithSpan { + use crate::ast::SpanWrapped; + + SpanWrapped::empty_span(Ident::new(value)) + } + #[test] fn test_window_frame_default() { let window_frame = WindowFrame::default(); @@ -4172,84 +4251,72 @@ mod tests { fn test_grouping_sets_display() { // a and b in different group let grouping_sets = Expr::GroupingSets(vec![ - vec![Expr::Identifier(Ident::new("a"))], - vec![Expr::Identifier(Ident::new("b"))], + vec![Expr::Identifier(ident("a"))], + vec![Expr::Identifier(ident("b"))], ]); assert_eq!("GROUPING SETS ((a), (b))", format!("{grouping_sets}")); // a and b in the same group let grouping_sets = Expr::GroupingSets(vec![vec![ - Expr::Identifier(Ident::new("a")), - Expr::Identifier(Ident::new("b")), + Expr::Identifier(ident("a")), + Expr::Identifier(ident("b")), ]]); assert_eq!("GROUPING SETS ((a, b))", format!("{grouping_sets}")); // (a, b) and (c, d) in different group let grouping_sets = Expr::GroupingSets(vec![ - vec![ - Expr::Identifier(Ident::new("a")), - Expr::Identifier(Ident::new("b")), - ], - vec![ - Expr::Identifier(Ident::new("c")), - Expr::Identifier(Ident::new("d")), - ], + vec![Expr::Identifier(ident("a")), Expr::Identifier(ident("b"))], + vec![Expr::Identifier(ident("c")), Expr::Identifier(ident("d"))], ]); assert_eq!("GROUPING SETS ((a, b), (c, d))", format!("{grouping_sets}")); } #[test] fn test_rollup_display() { - let rollup = Expr::Rollup(vec![vec![Expr::Identifier(Ident::new("a"))]]); + let rollup = Expr::Rollup(vec![vec![Expr::Identifier(ident("a"))]]); assert_eq!("ROLLUP (a)", format!("{rollup}")); let rollup = Expr::Rollup(vec![vec![ - Expr::Identifier(Ident::new("a")), - Expr::Identifier(Ident::new("b")), + Expr::Identifier(ident("a")), + Expr::Identifier(ident("b")), ]]); assert_eq!("ROLLUP ((a, b))", format!("{rollup}")); let rollup = Expr::Rollup(vec![ - vec![Expr::Identifier(Ident::new("a"))], - vec![Expr::Identifier(Ident::new("b"))], + vec![Expr::Identifier(ident("a"))], + vec![Expr::Identifier(ident("b"))], ]); assert_eq!("ROLLUP (a, b)", format!("{rollup}")); let rollup = Expr::Rollup(vec![ - vec![Expr::Identifier(Ident::new("a"))], - vec![ - Expr::Identifier(Ident::new("b")), - Expr::Identifier(Ident::new("c")), - ], - vec![Expr::Identifier(Ident::new("d"))], + vec![Expr::Identifier(ident("a"))], + vec![Expr::Identifier(ident("b")), Expr::Identifier(ident("c"))], + vec![Expr::Identifier(ident("d"))], ]); assert_eq!("ROLLUP (a, (b, c), d)", format!("{rollup}")); } #[test] fn test_cube_display() { - let cube = Expr::Cube(vec![vec![Expr::Identifier(Ident::new("a"))]]); + let cube = Expr::Cube(vec![vec![Expr::Identifier(ident("a"))]]); assert_eq!("CUBE (a)", format!("{cube}")); let cube = Expr::Cube(vec![vec![ - Expr::Identifier(Ident::new("a")), - Expr::Identifier(Ident::new("b")), + Expr::Identifier(ident("a")), + Expr::Identifier(ident("b")), ]]); assert_eq!("CUBE ((a, b))", format!("{cube}")); let cube = Expr::Cube(vec![ - vec![Expr::Identifier(Ident::new("a"))], - vec![Expr::Identifier(Ident::new("b"))], + vec![Expr::Identifier(ident("a"))], + vec![Expr::Identifier(ident("b"))], ]); assert_eq!("CUBE (a, b)", format!("{cube}")); let cube = Expr::Cube(vec![ - vec![Expr::Identifier(Ident::new("a"))], - vec![ - Expr::Identifier(Ident::new("b")), - Expr::Identifier(Ident::new("c")), - ], - vec![Expr::Identifier(Ident::new("d"))], + vec![Expr::Identifier(ident("a"))], + vec![Expr::Identifier(ident("b")), Expr::Identifier(ident("c"))], + vec![Expr::Identifier(ident("d"))], ]); assert_eq!("CUBE (a, (b, c), d)", format!("{cube}")); } diff --git a/src/lib.rs b/src/lib.rs index 75209b054..663352ea1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -51,6 +51,7 @@ extern crate alloc; #[macro_use] #[cfg(test)] extern crate pretty_assertions; +extern crate core; pub mod ast; #[macro_use] diff --git a/src/parser.rs b/src/parser.rs index 98fe589d6..6af358a0e 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -21,6 +21,7 @@ use alloc::{ vec::Vec, }; use core::fmt; +use std::cmp::max; use log::debug; @@ -303,7 +304,7 @@ impl<'a> Parser<'a> { .into_iter() .map(|token| TokenWithLocation { token, - location: Location { line: 0, column: 0 }, + span: Span::default(), }) .collect(); self.with_tokens_with_locations(tokens_with_locations) @@ -318,8 +319,8 @@ impl<'a> Parser<'a> { pub fn try_with_sql(self, sql: &str) -> Result { debug!("Parsing sql '{}'...", sql); let mut tokenizer = Tokenizer::new(self.dialect, sql); - let tokens = tokenizer.tokenize()?; - Ok(self.with_tokens(tokens)) + let tokens = tokenizer.tokenize_with_location()?; + Ok(self.with_tokens_with_locations(tokens)) } /// Parse potentially multiple statements @@ -495,7 +496,7 @@ impl<'a> Parser<'a> { let mut noscan = false; let mut partitions = None; let mut compute_statistics = false; - let mut columns = vec![]; + let mut columns: Vec = vec![]; loop { match self.parse_one_of_keywords(&[ Keyword::PARTITION, @@ -514,8 +515,12 @@ impl<'a> Parser<'a> { self.expect_keyword(Keyword::COLUMNS)?; columns = self - .maybe_parse(|parser| { - parser.parse_comma_separated(Parser::parse_identifier) + .maybe_parse::, _>(|parser| { + parser.parse_comma_separated(|p| { + let result: Result = + p.parse_identifier().map(|i| i.unwrap()); + result + }) }) .unwrap_or_default(); for_columns = true @@ -642,7 +647,9 @@ impl<'a> Parser<'a> { pub fn parse_savepoint(&mut self) -> Result { let name = self.parse_identifier()?; - Ok(Statement::Savepoint { name }) + Ok(Statement::Savepoint { + name: name.unwrap(), + }) } /// Parse an expression prefix @@ -779,7 +786,7 @@ impl<'a> Parser<'a> { value: self.parse_introduced_string_value()?, }) } - _ => Ok(Expr::Identifier(w.to_ident())), + _ => Ok(Expr::Identifier(w.to_ident().spanning(next_token.span))), }, }, // End of Token::Word // array `[1, 2, 3]` @@ -2077,13 +2084,17 @@ impl<'a> Parser<'a> { match self.tokens.get(index - 1) { Some(TokenWithLocation { token: Token::Whitespace(_), - location: _, + span: _, }) => continue, non_whitespace => { if n == 0 { return non_whitespace.cloned().unwrap_or(TokenWithLocation { token: Token::EOF, - location: Location { line: 0, column: 0 }, + span: self + .tokens + .last() + .map(|t| t.span.end.span_to(t.span.end)) + .unwrap_or_default(), }); } n -= 1; @@ -2101,12 +2112,16 @@ impl<'a> Parser<'a> { match self.tokens.get(self.index - 1) { Some(TokenWithLocation { token: Token::Whitespace(_), - location: _, + span: _, }) => continue, token => { - return token - .cloned() - .unwrap_or_else(|| TokenWithLocation::wrap(Token::EOF)) + return token.cloned().unwrap_or_else(|| { + let eof_span: Option = self + .tokens + .get(max(2, self.index) - 2) + .map(|t| t.span.end.span_to(t.span.end)); + TokenWithLocation::new(Token::EOF, eof_span.unwrap_or_default()) + }) } } } @@ -2127,7 +2142,7 @@ impl<'a> Parser<'a> { self.index -= 1; if let Some(TokenWithLocation { token: Token::Whitespace(_), - location: _, + span: _, }) = self.tokens.get(self.index) { continue; @@ -2485,7 +2500,7 @@ impl<'a> Parser<'a> { Ok(Statement::CreateVirtualTable { name: table_name, if_not_exists, - module_name, + module_name: module_name.unwrap(), module_args, }) } @@ -2503,14 +2518,16 @@ impl<'a> Parser<'a> { fn parse_schema_name(&mut self) -> Result { if self.parse_keyword(Keyword::AUTHORIZATION) { - Ok(SchemaName::UnnamedAuthorization(self.parse_identifier()?)) + Ok(SchemaName::UnnamedAuthorization( + self.parse_identifier()?.unwrap(), + )) } else { let name = self.parse_object_name()?; if self.parse_keyword(Keyword::AUTHORIZATION) { Ok(SchemaName::NamedAuthorization( name, - self.parse_identifier()?, + self.parse_identifier()?.unwrap(), )) } else { Ok(SchemaName::Simple(name)) @@ -2669,7 +2686,7 @@ impl<'a> Parser<'a> { body.as_ = Some(self.parse_function_definition()?); } else if self.parse_keyword(Keyword::LANGUAGE) { ensure_not_set(&body.language, "LANGUAGE")?; - body.language = Some(self.parse_identifier()?); + body.language = Some(self.parse_identifier()?.unwrap()); } else if self.parse_keyword(Keyword::IMMUTABLE) { ensure_not_set(&body.behavior, "IMMUTABLE | STABLE | VOLATILE")?; body.behavior = Some(FunctionBehavior::Immutable); @@ -2940,14 +2957,18 @@ impl<'a> Parser<'a> { if !in_role.is_empty() { parser_err!("Found multiple IN ROLE") } else { - in_role = self.parse_comma_separated(Parser::parse_identifier)?; + in_role = self.parse_comma_separated(|p| { + p.parse_identifier().map(WithSpan::unwrap) + })?; Ok(()) } } else if self.parse_keyword(Keyword::GROUP) { if !in_group.is_empty() { parser_err!("Found multiple IN GROUP") } else { - in_group = self.parse_comma_separated(Parser::parse_identifier)?; + in_group = self.parse_comma_separated(|p| { + p.parse_identifier().map(WithSpan::unwrap) + })?; Ok(()) } } else { @@ -2958,7 +2979,9 @@ impl<'a> Parser<'a> { if !role.is_empty() { parser_err!("Found multiple ROLE") } else { - role = self.parse_comma_separated(Parser::parse_identifier)?; + role = self.parse_comma_separated(|p| { + p.parse_identifier().map(WithSpan::unwrap) + })?; Ok(()) } } @@ -2966,7 +2989,9 @@ impl<'a> Parser<'a> { if !user.is_empty() { parser_err!("Found multiple USER") } else { - user = self.parse_comma_separated(Parser::parse_identifier)?; + user = self.parse_comma_separated(|p| { + p.parse_identifier().map(WithSpan::unwrap) + })?; Ok(()) } } @@ -2974,7 +2999,9 @@ impl<'a> Parser<'a> { if !admin.is_empty() { parser_err!("Found multiple ADMIN") } else { - admin = self.parse_comma_separated(Parser::parse_identifier)?; + admin = self.parse_comma_separated(|p| { + p.parse_identifier().map(WithSpan::unwrap) + })?; Ok(()) } } @@ -3090,7 +3117,7 @@ impl<'a> Parser<'a> { /// CURSOR [ { WITH | WITHOUT } HOLD ] FOR query /// ``` pub fn parse_declare(&mut self) -> Result { - let name = self.parse_identifier()?; + let name = self.parse_identifier()?.unwrap(); let binary = self.parse_keyword(Keyword::BINARY); let sensitive = if self.parse_keyword(Keyword::INSENSITIVE) { @@ -3183,7 +3210,7 @@ impl<'a> Parser<'a> { self.expect_one_of_keywords(&[Keyword::FROM, Keyword::IN])?; - let name = self.parse_identifier()?; + let name = self.parse_identifier()?.unwrap(); let into = if self.parse_keyword(Keyword::INTO) { Some(self.parse_object_name()?) @@ -3222,7 +3249,7 @@ impl<'a> Parser<'a> { self.expect_keyword(Keyword::ON)?; let table_name = self.parse_object_name()?; let using = if self.parse_keyword(Keyword::USING) { - Some(self.parse_identifier()?) + Some(self.parse_identifier()?.unwrap()) } else { None }; @@ -3355,14 +3382,14 @@ impl<'a> Parser<'a> { let order_by = if self.parse_keywords(&[Keyword::ORDER, Keyword::BY]) { if self.consume_token(&Token::LParen) { let columns = if self.peek_token() != Token::RParen { - self.parse_comma_separated(Parser::parse_identifier)? + self.parse_comma_separated(|p| p.parse_identifier().map(WithSpan::unwrap))? } else { vec![] }; self.expect_token(&Token::RParen)?; Some(columns) } else { - Some(vec![self.parse_identifier()?]) + Some(vec![self.parse_identifier()?.unwrap()]) } } else { None @@ -3467,7 +3494,7 @@ impl<'a> Parser<'a> { } pub fn parse_column_def(&mut self) -> Result { - let name = self.parse_identifier()?; + let name = self.parse_identifier()?.unwrap(); let data_type = self.parse_data_type()?; let collation = if self.parse_keyword(Keyword::COLLATE) { Some(self.parse_object_name()?) @@ -3477,7 +3504,7 @@ impl<'a> Parser<'a> { let mut options = vec![]; loop { if self.parse_keyword(Keyword::CONSTRAINT) { - let name = Some(self.parse_identifier()?); + let name = Some(self.parse_identifier()?.unwrap()); if let Some(option) = self.parse_optional_column_option()? { options.push(ColumnOptionDef { name, option }); } else { @@ -3644,7 +3671,7 @@ impl<'a> Parser<'a> { &mut self, ) -> Result, ParserError> { let name = if self.parse_keyword(Keyword::CONSTRAINT) { - Some(self.parse_identifier()?) + Some(self.parse_identifier()?.unwrap()) } else { None }; @@ -3705,7 +3732,7 @@ impl<'a> Parser<'a> { let name = match self.peek_token().token { Token::Word(word) if word.keyword == Keyword::USING => None, - _ => self.maybe_parse(|parser| parser.parse_identifier()), + _ => self.maybe_parse(|p| p.parse_identifier().map(WithSpan::unwrap)), }; let index_type = if self.parse_keyword(Keyword::USING) { @@ -3731,7 +3758,7 @@ impl<'a> Parser<'a> { "FULLTEXT or SPATIAL option without constraint name", TokenWithLocation { token: Token::make_keyword(&name.to_string()), - location: next_token.location, + span: next_token.span, }, ); } @@ -3746,7 +3773,8 @@ impl<'a> Parser<'a> { KeyOrIndexDisplay::None }; - let opt_index_name = self.maybe_parse(|parser| parser.parse_identifier()); + let opt_index_name = + self.maybe_parse(|p| p.parse_identifier().map(WithSpan::unwrap)); let columns = self.parse_parenthesized_column_list(Mandatory, false)?; @@ -3790,7 +3818,7 @@ impl<'a> Parser<'a> { } pub fn parse_sql_option(&mut self) -> Result { - let name = self.parse_identifier()?; + let name = self.parse_identifier()?.unwrap(); self.expect_token(&Token::Eq)?; let value = self.parse_value()?; Ok(SqlOption { name, value }) @@ -3839,18 +3867,18 @@ impl<'a> Parser<'a> { if dialect_of!(self is PostgreSqlDialect) && self.parse_keyword(Keyword::CONSTRAINT) { - let old_name = self.parse_identifier()?; + let old_name = self.parse_identifier()?.unwrap(); self.expect_keyword(Keyword::TO)?; - let new_name = self.parse_identifier()?; + let new_name = self.parse_identifier()?.unwrap(); AlterTableOperation::RenameConstraint { old_name, new_name } } else if self.parse_keyword(Keyword::TO) { let table_name = self.parse_object_name()?; AlterTableOperation::RenameTable { table_name } } else { let _ = self.parse_keyword(Keyword::COLUMN); // [ COLUMN ] - let old_column_name = self.parse_identifier()?; + let old_column_name = self.parse_identifier()?.unwrap(); self.expect_keyword(Keyword::TO)?; - let new_column_name = self.parse_identifier()?; + let new_column_name = self.parse_identifier()?.unwrap(); AlterTableOperation::RenameColumn { old_column_name, new_column_name, @@ -3875,7 +3903,7 @@ impl<'a> Parser<'a> { } } else if self.parse_keyword(Keyword::CONSTRAINT) { let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]); - let name = self.parse_identifier()?; + let name = self.parse_identifier()?.unwrap(); let cascade = self.parse_keyword(Keyword::CASCADE); AlterTableOperation::DropConstraint { if_exists, @@ -3889,7 +3917,7 @@ impl<'a> Parser<'a> { } else { let _ = self.parse_keyword(Keyword::COLUMN); // [ COLUMN ] let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]); - let column_name = self.parse_identifier()?; + let column_name = self.parse_identifier()?.unwrap(); let cascade = self.parse_keyword(Keyword::CASCADE); AlterTableOperation::DropColumn { column_name, @@ -3912,8 +3940,8 @@ impl<'a> Parser<'a> { } } else if self.parse_keyword(Keyword::CHANGE) { let _ = self.parse_keyword(Keyword::COLUMN); // [ COLUMN ] - let old_name = self.parse_identifier()?; - let new_name = self.parse_identifier()?; + let old_name = self.parse_identifier()?.unwrap(); + let new_name = self.parse_identifier()?.unwrap(); let data_type = self.parse_data_type()?; let mut options = vec![]; while let Some(option) = self.parse_optional_column_option()? { @@ -3928,7 +3956,7 @@ impl<'a> Parser<'a> { } } else if self.parse_keyword(Keyword::ALTER) { let _ = self.parse_keyword(Keyword::COLUMN); // [ COLUMN ] - let column_name = self.parse_identifier()?; + let column_name = self.parse_identifier()?.unwrap(); let is_postgresql = dialect_of!(self is PostgreSqlDialect); let op = if self.parse_keywords(&[Keyword::SET, Keyword::NOT, Keyword::NULL]) { @@ -4049,7 +4077,7 @@ impl<'a> Parser<'a> { let cursor = if self.parse_keyword(Keyword::ALL) { CloseCursor::All } else { - let name = self.parse_identifier()?; + let name = self.parse_identifier()?.unwrap(); CloseCursor::Specific { name } }; @@ -4071,7 +4099,7 @@ impl<'a> Parser<'a> { Keyword::FORCE_NULL, Keyword::ENCODING, ]) { - Some(Keyword::FORMAT) => CopyOption::Format(self.parse_identifier()?), + Some(Keyword::FORMAT) => CopyOption::Format(self.parse_identifier()?.unwrap()), Some(Keyword::FREEZE) => CopyOption::Freeze(!matches!( self.parse_one_of_keywords(&[Keyword::TRUE, Keyword::FALSE]), Some(Keyword::FALSE) @@ -4147,12 +4175,12 @@ impl<'a> Parser<'a> { } Some(Keyword::FORCE) if self.parse_keywords(&[Keyword::NOT, Keyword::NULL]) => { CopyLegacyCsvOption::ForceNotNull( - self.parse_comma_separated(Parser::parse_identifier)?, + self.parse_comma_separated(|p| p.parse_identifier().map(WithSpan::unwrap))?, ) } Some(Keyword::FORCE) if self.parse_keywords(&[Keyword::QUOTE]) => { CopyLegacyCsvOption::ForceQuote( - self.parse_comma_separated(Parser::parse_identifier)?, + self.parse_comma_separated(|p| p.parse_identifier().map(WithSpan::unwrap))?, ) } _ => self.expected("csv option", self.peek_token())?, @@ -4208,7 +4236,7 @@ impl<'a> Parser<'a> { /// Parse a literal value (numbers, strings, date/time, booleans) pub fn parse_value(&mut self) -> Result { let next_token = self.next_token(); - let location = next_token.location; + let span = next_token.span; match next_token.token { Token::Word(w) => match w.keyword { Keyword::TRUE => Ok(Value::Boolean(true)), @@ -4221,7 +4249,7 @@ impl<'a> Parser<'a> { "A value?", TokenWithLocation { token: Token::Word(w), - location, + span, }, )?, }, @@ -4233,7 +4261,7 @@ impl<'a> Parser<'a> { "a concrete value", TokenWithLocation { token: Token::Word(w), - location, + span, }, ), }, @@ -4267,7 +4295,7 @@ impl<'a> Parser<'a> { "a value", TokenWithLocation { token: unexpected, - location, + span, }, ), } @@ -4286,7 +4314,7 @@ impl<'a> Parser<'a> { fn parse_introduced_string_value(&mut self) -> Result { let next_token = self.next_token(); - let location = next_token.location; + let span = next_token.span; match next_token.token { Token::SingleQuotedString(ref s) => Ok(Value::SingleQuotedString(s.to_string())), Token::DoubleQuotedString(ref s) => Ok(Value::DoubleQuotedString(s.to_string())), @@ -4295,7 +4323,7 @@ impl<'a> Parser<'a> { "a string value", TokenWithLocation { token: unexpected, - location, + span, }, ), } @@ -4575,9 +4603,9 @@ impl<'a> Parser<'a> { /// Strictly parse `identifier AS identifier` pub fn parse_identifier_with_alias(&mut self) -> Result { - let ident = self.parse_identifier()?; + let ident = self.parse_identifier()?.unwrap(); self.expect_keyword(Keyword::AS)?; - let alias = self.parse_identifier()?; + let alias = self.parse_identifier()?.unwrap(); Ok(IdentWithAlias { ident, alias }) } @@ -4646,7 +4674,7 @@ impl<'a> Parser<'a> { pub fn parse_object_name(&mut self) -> Result { let mut idents = vec![]; loop { - idents.push(self.parse_identifier()?); + idents.push(self.parse_identifier()?.unwrap()); if !self.consume_token(&Token::Period) { break; } @@ -4671,12 +4699,16 @@ impl<'a> Parser<'a> { } /// Parse a simple one-word identifier (possibly quoted, possibly a keyword) - pub fn parse_identifier(&mut self) -> Result { + pub fn parse_identifier(&mut self) -> Result, ParserError> { let next_token = self.next_token(); match next_token.token { - Token::Word(w) => Ok(w.to_ident()), - Token::SingleQuotedString(s) => Ok(Ident::with_quote('\'', s)), - Token::DoubleQuotedString(s) => Ok(Ident::with_quote('\"', s)), + Token::Word(w) => Ok(w.to_ident().spanning(next_token.span)), + Token::SingleQuotedString(s) => { + Ok(Ident::with_quote('\'', s).spanning(next_token.span)) + } + Token::DoubleQuotedString(s) => { + Ok(Ident::with_quote('\"', s).spanning(next_token.span)) + } _ => self.expected("identifier", next_token), } } @@ -4692,7 +4724,8 @@ impl<'a> Parser<'a> { self.next_token(); Ok(vec![]) } else { - let cols = self.parse_comma_separated(Parser::parse_identifier)?; + let cols = + self.parse_comma_separated(|p| p.parse_identifier().map(WithSpan::unwrap))?; self.expect_token(&Token::RParen)?; Ok(cols) } @@ -4981,7 +5014,7 @@ impl<'a> Parser<'a> { /// Parse a CTE (`alias [( col1, col2, ... )] AS (subquery)`) pub fn parse_cte(&mut self) -> Result { - let name = self.parse_identifier()?; + let name = self.parse_identifier()?.unwrap(); let mut cte = if self.parse_keyword(Keyword::AS) { self.expect_token(&Token::LParen)?; @@ -5010,7 +5043,7 @@ impl<'a> Parser<'a> { } }; if self.parse_keyword(Keyword::FROM) { - cte.from = Some(self.parse_identifier()?); + cte.from = Some(self.parse_identifier()?.unwrap()); } Ok(cte) } @@ -5296,7 +5329,7 @@ impl<'a> Parser<'a> { let role_name = if self.parse_keyword(Keyword::NONE) { None } else { - Some(self.parse_identifier()?) + Some(self.parse_identifier()?.unwrap()) }; return Ok(Statement::SetRole { context_modifier, @@ -5451,7 +5484,7 @@ impl<'a> Parser<'a> { let object_name = self.parse_object_name()?; let table_name = match self.parse_one_of_keywords(&[Keyword::FROM, Keyword::IN]) { Some(_) => { - let db_name = vec![self.parse_identifier()?]; + let db_name = vec![self.parse_identifier()?.unwrap()]; let ObjectName(table_name) = object_name; let object_name = db_name.into_iter().chain(table_name.into_iter()).collect(); ObjectName(object_name) @@ -5473,7 +5506,7 @@ impl<'a> Parser<'a> { full: bool, ) -> Result { let db_name = match self.parse_one_of_keywords(&[Keyword::FROM, Keyword::IN]) { - Some(_) => Some(self.parse_identifier()?), + Some(_) => Some(self.parse_identifier()?.unwrap()), None => None, }; let filter = self.parse_show_statement_filter()?; @@ -5514,7 +5547,7 @@ impl<'a> Parser<'a> { } pub fn parse_use(&mut self) -> Result { - let db_name = self.parse_identifier()?; + let db_name = self.parse_identifier()?.unwrap(); Ok(Statement::Use { db_name }) } @@ -5842,14 +5875,17 @@ impl<'a> Parser<'a> { let (privileges, objects) = self.parse_grant_revoke_privileges_objects()?; self.expect_keyword(Keyword::TO)?; - let grantees = self.parse_comma_separated(Parser::parse_identifier)?; + let grantees = + self.parse_comma_separated(|p| p.parse_identifier().map(WithSpan::unwrap))?; let with_grant_option = self.parse_keywords(&[Keyword::WITH, Keyword::GRANT, Keyword::OPTION]); let granted_by = self .parse_keywords(&[Keyword::GRANTED, Keyword::BY]) - .then(|| self.parse_identifier().unwrap()); + .then(|| self.parse_identifier()) // Possible panic fixed + .transpose()? + .map(WithSpan::unwrap); Ok(Statement::Grant { privileges, @@ -5973,11 +6009,14 @@ impl<'a> Parser<'a> { let (privileges, objects) = self.parse_grant_revoke_privileges_objects()?; self.expect_keyword(Keyword::FROM)?; - let grantees = self.parse_comma_separated(Parser::parse_identifier)?; + let grantees = + self.parse_comma_separated(|p| p.parse_identifier().map(WithSpan::unwrap))?; let granted_by = self .parse_keywords(&[Keyword::GRANTED, Keyword::BY]) - .then(|| self.parse_identifier().unwrap()); + .then(|| self.parse_identifier()) // panic fixed + .transpose()? + .map(WithSpan::unwrap); let cascade = self.parse_keyword(Keyword::CASCADE); let restrict = self.parse_keyword(Keyword::RESTRICT); @@ -6164,7 +6203,7 @@ impl<'a> Parser<'a> { pub fn parse_function_args(&mut self) -> Result { if self.peek_nth_token(1) == Token::RArrow { - let name = self.parse_identifier()?; + let name = self.parse_identifier()?.unwrap(); self.expect_token(&Token::RArrow)?; let arg = self.parse_wildcard_expr()?.into(); @@ -6267,11 +6306,13 @@ impl<'a> Parser<'a> { ) -> Result, ParserError> { let opt_exclude = if self.parse_keyword(Keyword::EXCLUDE) { if self.consume_token(&Token::LParen) { - let columns = self.parse_comma_separated(|parser| parser.parse_identifier())?; + let columns = self.parse_comma_separated(|parser| { + parser.parse_identifier().map(WithSpan::unwrap) + })?; self.expect_token(&Token::RParen)?; Some(ExcludeSelectItem::Multiple(columns)) } else { - let column = self.parse_identifier()?; + let column = self.parse_identifier()?.unwrap(); Some(ExcludeSelectItem::Single(column)) } } else { @@ -6353,10 +6394,10 @@ impl<'a> Parser<'a> { pub fn parse_replace_elements(&mut self) -> Result { let expr = self.parse_expr()?; let as_keyword = self.parse_keyword(Keyword::AS); - let ident = self.parse_identifier()?; + let column_name = self.parse_identifier()?.unwrap(); Ok(ReplaceSelectElement { expr, - column_name: ident, + column_name, as_keyword, }) } @@ -6582,12 +6623,12 @@ impl<'a> Parser<'a> { pub fn parse_deallocate(&mut self) -> Result { let prepare = self.parse_keyword(Keyword::PREPARE); - let name = self.parse_identifier()?; + let name = self.parse_identifier()?.unwrap(); Ok(Statement::Deallocate { name, prepare }) } pub fn parse_execute(&mut self) -> Result { - let name = self.parse_identifier()?; + let name = self.parse_identifier()?.unwrap(); let mut parameters = vec![]; if self.consume_token(&Token::LParen) { @@ -6599,7 +6640,7 @@ impl<'a> Parser<'a> { } pub fn parse_prepare(&mut self) -> Result { - let name = self.parse_identifier()?; + let name = self.parse_identifier()?.unwrap(); let mut data_types = vec![]; if self.consume_token(&Token::LParen) { diff --git a/src/tokenizer.rs b/src/tokenizer.rs index bc6e3addb..e3b72dfe6 100644 --- a/src/tokenizer.rs +++ b/src/tokenizer.rs @@ -27,6 +27,8 @@ use alloc::{ use core::fmt; use core::iter::Peekable; use core::str::Chars; +use std::cmp::{max, min}; +use std::ops::Range; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; @@ -338,32 +340,135 @@ impl fmt::Display for Whitespace { } } +pub type LineNumber = u64; +pub type ColumnPosition = u64; +pub type LineColumn = (LineNumber, ColumnPosition); + /// Location in input string -#[derive(Debug, Eq, PartialEq, Clone)] +#[derive(Debug, Eq, PartialEq, Clone, Copy, Ord, PartialOrd, Hash)] pub struct Location { /// Line number, starting from 1 - pub line: u64, + pub line: LineNumber, /// Line column, starting from 1 - pub column: u64, + pub column: ColumnPosition, +} + +impl Default for Location { + fn default() -> Self { + Self { line: 1, column: 1 } + } +} + +impl From for Location { + fn from(value: LineColumn) -> Self { + Location { + line: value.0, + column: value.1, + } + } +} + +impl From for Location { + fn from(value: u64) -> Self { + Location { + line: 1, + column: value, + } + } +} + +impl From for Location { + fn from(value: usize) -> Self { + Location { + line: 1, + column: value as u64, + } + } } -/// A [Token] with [Location] attached to it +impl From for Location { + fn from(value: i32) -> Self { + Location { + line: 1, + column: value as u64, + } + } +} + +impl Location { + pub fn of(line: LineNumber, column: ColumnPosition) -> Self { + Self { line, column } + } + + pub fn span_to(self, end: Self) -> Span { + Span { start: self, end } + } +} + +/// Location in input string +#[derive(Debug, Eq, PartialEq, Clone, Copy, Default, Ord, PartialOrd, Hash)] +pub struct Span { + /// The span start location, inclusive. + pub start: Location, + /// The span end location, exclusive. + pub end: Location, +} + +impl Span { + pub fn new, U: Into>(start: T, end: U) -> Self { + Self { + start: start.into(), + end: end.into(), + } + } + + pub fn zero_width(start: Location) -> Self { + Self { start, end: start } + } + + pub fn union(self, other: Self) -> Self { + Self { + start: min(self.start, other.start), + end: max(self.end, other.end), + } + } + + pub fn start(self) -> Location { + self.start + } + + pub fn end(self) -> Location { + self.end + } +} + +impl> From> for Span { + fn from(value: Range) -> Self { + Span::new(value.start.into(), value.end.into()) + } +} + +/// A [Token] with [Span] attached to it #[derive(Debug, Eq, PartialEq, Clone)] pub struct TokenWithLocation { pub token: Token, - pub location: Location, + pub span: Span, } impl TokenWithLocation { - pub fn new(token: Token, line: u64, column: u64) -> TokenWithLocation { + pub fn new(token: Token, span: Span) -> TokenWithLocation { + TokenWithLocation { token, span } + } + + pub fn at(token: Token, start: LineColumn, end: LineColumn) -> TokenWithLocation { TokenWithLocation { token, - location: Location { line, column }, + span: Location::from(start).span_to(end.into()), } } pub fn wrap(token: Token) -> TokenWithLocation { - TokenWithLocation::new(token, 0, 0) + TokenWithLocation::new(token, Span::default()) } } @@ -476,10 +581,8 @@ impl<'a> Tokenizer<'a> { let mut location = state.location(); while let Some(token) = self.next_token(&mut state)? { - tokens.push(TokenWithLocation { - token, - location: location.clone(), - }); + let span = location.span_to(state.location()); + tokens.push(TokenWithLocation { token, span }); location = state.location(); } @@ -1862,13 +1965,13 @@ mod tests { let mut tokenizer = Tokenizer::new(&dialect, sql); let tokens = tokenizer.tokenize_with_location().unwrap(); let expected = vec![ - TokenWithLocation::new(Token::make_keyword("SELECT"), 1, 1), - TokenWithLocation::new(Token::Whitespace(Whitespace::Space), 1, 7), - TokenWithLocation::new(Token::make_word("a", None), 1, 8), - TokenWithLocation::new(Token::Comma, 1, 9), - TokenWithLocation::new(Token::Whitespace(Whitespace::Newline), 1, 10), - TokenWithLocation::new(Token::Whitespace(Whitespace::Space), 2, 1), - TokenWithLocation::new(Token::make_word("b", None), 2, 2), + TokenWithLocation::at(Token::make_keyword("SELECT"), (1, 1), (1, 7)), + TokenWithLocation::at(Token::Whitespace(Whitespace::Space), (1, 7), (1, 8)), + TokenWithLocation::at(Token::make_word("a", None), (1, 8), (1, 9)), + TokenWithLocation::at(Token::Comma, (1, 9), (1, 10)), + TokenWithLocation::at(Token::Whitespace(Whitespace::Newline), (1, 10), (2, 1)), + TokenWithLocation::at(Token::Whitespace(Whitespace::Space), (2, 1), (2, 2)), + TokenWithLocation::at(Token::make_word("b", None), (2, 2), (2, 3)), ]; compare(expected, tokens); } diff --git a/tests/sqlparser_bigquery.rs b/tests/sqlparser_bigquery.rs index 11a8c6e5c..89d64dfd2 100644 --- a/tests/sqlparser_bigquery.rs +++ b/tests/sqlparser_bigquery.rs @@ -19,6 +19,7 @@ use test_utils::*; #[cfg(feature = "bigdecimal")] use bigdecimal::*; +use sqlparser::tokenizer::Span; #[cfg(feature = "bigdecimal")] use std::str::FromStr; @@ -168,9 +169,13 @@ fn parse_join_constraint_unnest_alias() { with_offset_alias: None }, join_operator: JoinOperator::Inner(JoinConstraint::On(Expr::BinaryOp { - left: Box::new(Expr::Identifier("c1".into())), + left: Box::new(Expr::Identifier( + Ident::new("c1").spanning((1, 44)..(1, 46)) + )), op: BinaryOperator::Eq, - right: Box::new(Expr::Identifier("c2".into())), + right: Box::new(Expr::Identifier( + Ident::new("c2").spanning((1, 49)..(1, 51)) + )), })), }] ); @@ -209,7 +214,7 @@ fn parse_like() { let select = bigquery().verified_only_select(sql); assert_eq!( Expr::Like { - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier(Ident::new("name").spanning(31..35))), negated, pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))), escape_char: None, @@ -225,7 +230,7 @@ fn parse_like() { let select = bigquery().verified_only_select(sql); assert_eq!( Expr::Like { - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier(Ident::new("name").spanning(31..35))), negated, pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))), escape_char: Some('\\'), @@ -242,7 +247,7 @@ fn parse_like() { let select = bigquery().verified_only_select(sql); assert_eq!( Expr::IsNull(Box::new(Expr::Like { - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier(Ident::new("name").spanning(31..35))), negated, pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))), escape_char: None, @@ -264,7 +269,7 @@ fn parse_similar_to() { let select = bigquery().verified_only_select(sql); assert_eq!( Expr::SimilarTo { - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier(Ident::new("name").spanning(31..35))), negated, pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))), escape_char: None, @@ -280,7 +285,9 @@ fn parse_similar_to() { let select = bigquery().verified_only_select(sql); assert_eq!( Expr::SimilarTo { - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier( + Ident::new("name").spanning(span_for("name", sql)) + )), negated, pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))), escape_char: Some('\\'), @@ -296,7 +303,9 @@ fn parse_similar_to() { let select = bigquery().verified_only_select(sql); assert_eq!( Expr::IsNull(Box::new(Expr::SimilarTo { - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier( + Ident::new("name").spanning(span_for("name", sql)) + )), negated, pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))), escape_char: Some('\\'), @@ -304,6 +313,15 @@ fn parse_similar_to() { select.selection.unwrap() ); } + + fn span_for(target: &str, source: &str) -> Span { + let Some(idx) = source.find(target) else { + return Span::default() + }; + + ((idx + 1)..(target.len() + idx + 1)).into() + } + chk(false); chk(true); } @@ -375,7 +393,7 @@ fn test_select_wildcard_with_replace() { items: vec![ Box::new(ReplaceSelectElement { expr: Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident::new("quantity"))), + left: Box::new(Expr::Identifier(Ident::new("quantity").spanning(19..27))), op: BinaryOperator::Divide, #[cfg(not(feature = "bigdecimal"))] right: Box::new(Expr::Value(Value::Number("2".to_string(), false))), @@ -423,10 +441,13 @@ fn parse_map_access_offset() { assert_eq!( _select.projection[0], SelectItem::UnnamedExpr(Expr::MapAccess { - column: Box::new(Expr::Identifier(Ident { - value: "d".to_string(), - quote_style: None, - })), + column: Box::new(Expr::Identifier( + Ident { + value: "d".to_string(), + quote_style: None, + } + .spanning(8..9) + )), keys: vec![Expr::Function(Function { name: ObjectName(vec!["offset".into()]), args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value( diff --git a/tests/sqlparser_clickhouse.rs b/tests/sqlparser_clickhouse.rs index 3ee3fbc03..b098d2ffa 100644 --- a/tests/sqlparser_clickhouse.rs +++ b/tests/sqlparser_clickhouse.rs @@ -25,6 +25,7 @@ use sqlparser::ast::TableFactor::Table; use sqlparser::ast::*; use sqlparser::dialect::ClickHouseDialect; +use sqlparser::tokenizer::Span; #[test] fn parse_map_access_expr() { @@ -35,16 +36,19 @@ fn parse_map_access_expr() { distinct: false, top: None, projection: vec![UnnamedExpr(MapAccess { - column: Box::new(Identifier(Ident { - value: "string_values".to_string(), - quote_style: None, - })), + column: Box::new(Identifier( + Ident { + value: "string_values".to_string(), + quote_style: None, + } + .spanning(8..21) + )), keys: vec![Expr::Function(Function { name: ObjectName(vec!["indexOf".into()]), args: vec![ - FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Identifier(Ident::new( - "string_names" - )))), + FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Identifier( + Ident::new("string_names").spanning(30..42) + ))), FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value( Value::SingleQuotedString("endpoint".to_string()) ))), @@ -67,19 +71,19 @@ fn parse_map_access_expr() { lateral_views: vec![], selection: Some(BinaryOp { left: Box::new(BinaryOp { - left: Box::new(Identifier(Ident::new("id"))), + left: Box::new(Identifier(Ident::new("id").spanning(73..75))), op: BinaryOperator::Eq, right: Box::new(Expr::Value(Value::SingleQuotedString("test".to_string()))) }), op: BinaryOperator::And, right: Box::new(BinaryOp { left: Box::new(MapAccess { - column: Box::new(Identifier(Ident::new("string_value"))), + column: Box::new(Identifier(Ident::new("string_value").spanning(89..101))), keys: vec![Expr::Function(Function { name: ObjectName(vec![Ident::new("indexOf")]), args: vec![ FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Identifier( - Ident::new("string_name") + Ident::new("string_name").spanning(110..121) ))), FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Value( Value::SingleQuotedString("app".to_string()) @@ -129,8 +133,12 @@ fn parse_array_fn() { &Expr::Function(Function { name: ObjectName(vec![Ident::new("array")]), args: vec![ - FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Identifier(Ident::new("x1")))), - FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Identifier(Ident::new("x2")))), + FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Identifier( + Ident::new("x1").spanning((1, 14)..(1, 16)) + ))), + FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Identifier( + Ident::new("x2").spanning((1, 18)..(1, 20)) + ))), ], over: None, distinct: false, @@ -194,7 +202,10 @@ fn parse_delimited_identifiers() { ); match &select.projection[2] { SelectItem::ExprWithAlias { expr, alias } => { - assert_eq!(&Expr::Identifier(Ident::with_quote('"', "simple id")), expr); + assert_eq!( + &Expr::Identifier(Ident::with_quote('"', "simple id").spanning(38..49)), + expr + ); assert_eq!(&Ident::with_quote('"', "column alias"), alias); } _ => panic!("Expected ExprWithAlias"), @@ -215,7 +226,7 @@ fn parse_like() { let select = clickhouse().verified_only_select(sql); assert_eq!( Expr::Like { - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier(Ident::new("name").spanning(31..35))), negated, pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))), escape_char: None, @@ -231,7 +242,7 @@ fn parse_like() { let select = clickhouse().verified_only_select(sql); assert_eq!( Expr::Like { - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier(Ident::new("name").spanning(31..35))), negated, pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))), escape_char: Some('\\'), @@ -248,7 +259,7 @@ fn parse_like() { let select = clickhouse().verified_only_select(sql); assert_eq!( Expr::IsNull(Box::new(Expr::Like { - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier(Ident::new("name").spanning(31..35))), negated, pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))), escape_char: None, @@ -270,7 +281,7 @@ fn parse_similar_to() { let select = clickhouse().verified_only_select(sql); assert_eq!( Expr::SimilarTo { - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier(Ident::new("name").spanning(31..35))), negated, pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))), escape_char: None, @@ -286,7 +297,7 @@ fn parse_similar_to() { let select = clickhouse().verified_only_select(sql); assert_eq!( Expr::SimilarTo { - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier(Ident::new("name").spanning(31..35))), negated, pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))), escape_char: Some('\\'), @@ -302,7 +313,7 @@ fn parse_similar_to() { let select = clickhouse().verified_only_select(sql); assert_eq!( Expr::IsNull(Box::new(Expr::SimilarTo { - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier(Ident::new("name").spanning(31..35))), negated, pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))), escape_char: Some('\\'), diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs index 55690da3a..acc14c211 100644 --- a/tests/sqlparser_common.rs +++ b/tests/sqlparser_common.rs @@ -28,6 +28,7 @@ use sqlparser::dialect::{ }; use sqlparser::keywords::ALL_KEYWORDS; use sqlparser::parser::{Parser, ParserError}; +use sqlparser::tokenizer::Span; use test_utils::{ all_dialects, assert_eq_vec, expr_from_projection, join, number, only, table, table_alias, TestedDialects, @@ -166,7 +167,10 @@ fn parse_update() { }, ] ); - assert_eq!(selection.unwrap(), Expr::Identifier("d".into())); + assert_eq!( + selection.unwrap(), + Expr::Identifier(Ident::new("d").empty_span()) + ); } _ => unreachable!(), } @@ -227,8 +231,12 @@ fn parse_update_set_from() { distinct: false, top: None, projection: vec![ - SelectItem::UnnamedExpr(Expr::Identifier(Ident::new("name"))), - SelectItem::UnnamedExpr(Expr::Identifier(Ident::new("id"))), + SelectItem::UnnamedExpr(Expr::Identifier( + Ident::new("name").empty_span() + )), + SelectItem::UnnamedExpr(Expr::Identifier( + Ident::new("id").empty_span() + )), ], into: None, from: vec![TableWithJoins { @@ -242,7 +250,7 @@ fn parse_update_set_from() { }], lateral_views: vec![], selection: None, - group_by: vec![Expr::Identifier(Ident::new("id"))], + group_by: vec![Expr::Identifier(Ident::new("id").empty_span())], cluster_by: vec![], distribute_by: vec![], sort_by: vec![], @@ -345,9 +353,9 @@ fn parse_select_with_table_alias() { assert_eq!( select.projection, vec![ - SelectItem::UnnamedExpr(Expr::Identifier(Ident::new("a")),), - SelectItem::UnnamedExpr(Expr::Identifier(Ident::new("b")),), - SelectItem::UnnamedExpr(Expr::Identifier(Ident::new("c")),), + SelectItem::UnnamedExpr(Expr::Identifier(Ident::new("a").empty_span()),), + SelectItem::UnnamedExpr(Expr::Identifier(Ident::new("b").empty_span()),), + SelectItem::UnnamedExpr(Expr::Identifier(Ident::new("c").empty_span()),), ] ); assert_eq!( @@ -424,7 +432,7 @@ fn parse_where_delete_statement() { assert_eq!(None, using); assert_eq!( Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident::new("name"))), + left: Box::new(Expr::Identifier(Ident::new("name").empty_span())), op: Eq, right: Box::new(Expr::Value(number("5"))), }, @@ -528,7 +536,7 @@ fn parse_select_distinct() { let select = verified_only_select(sql); assert!(select.distinct); assert_eq!( - &SelectItem::UnnamedExpr(Expr::Identifier(Ident::new("name"))), + &SelectItem::UnnamedExpr(Expr::Identifier(Ident::new("name").empty_span())), only(&select.projection) ); } @@ -539,11 +547,11 @@ fn parse_select_distinct_two_fields() { let select = verified_only_select(sql); assert!(select.distinct); assert_eq!( - &SelectItem::UnnamedExpr(Expr::Identifier(Ident::new("name"))), + &SelectItem::UnnamedExpr(Expr::Identifier(Ident::new("name").empty_span())), &select.projection[0] ); assert_eq!( - &SelectItem::UnnamedExpr(Expr::Identifier(Ident::new("id"))), + &SelectItem::UnnamedExpr(Expr::Identifier(Ident::new("id").empty_span())), &select.projection[1] ); } @@ -554,8 +562,8 @@ fn parse_select_distinct_tuple() { let select = verified_only_select(sql); assert_eq!( &vec![SelectItem::UnnamedExpr(Expr::Tuple(vec![ - Expr::Identifier(Ident::new("name")), - Expr::Identifier(Ident::new("id")), + Expr::Identifier(Ident::new("name").empty_span()), + Expr::Identifier(Ident::new("id").empty_span()), ]))], &select.projection ); @@ -731,7 +739,7 @@ fn parse_select_count_distinct() { name: ObjectName(vec![Ident::new("COUNT")]), args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::UnaryOp { op: UnaryOperator::Plus, - expr: Box::new(Expr::Identifier(Ident::new("x"))), + expr: Box::new(Expr::Identifier(Ident::new("x").empty_span())), }))], over: None, distinct: true, @@ -868,10 +876,13 @@ fn parse_select_with_date_column_name() { let sql = "SELECT date"; let select = verified_only_select(sql); assert_eq!( - &Expr::Identifier(Ident { - value: "date".into(), - quote_style: None, - }), + &Expr::Identifier( + Ident { + value: "date".into(), + quote_style: None, + } + .empty_span() + ), expr_from_projection(only(&select.projection)), ); } @@ -884,7 +895,7 @@ fn parse_escaped_single_quote_string_predicate() { let ast = verified_only_select(sql); assert_eq!( Some(Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident::new("salary"))), + left: Box::new(Expr::Identifier(Ident::new("salary").empty_span())), op: NotEq, right: Box::new(Expr::Value(Value::SingleQuotedString( "Jim's salary".to_string() @@ -915,12 +926,12 @@ fn parse_compound_expr_1() { let sql = "a + b * c"; assert_eq!( BinaryOp { - left: Box::new(Identifier(Ident::new("a"))), + left: Box::new(Identifier(Ident::new("a").empty_span())), op: Plus, right: Box::new(BinaryOp { - left: Box::new(Identifier(Ident::new("b"))), + left: Box::new(Identifier(Ident::new("b").empty_span())), op: Multiply, - right: Box::new(Identifier(Ident::new("c"))), + right: Box::new(Identifier(Ident::new("c").empty_span())), }), }, verified_expr(sql) @@ -935,12 +946,12 @@ fn parse_compound_expr_2() { assert_eq!( BinaryOp { left: Box::new(BinaryOp { - left: Box::new(Identifier(Ident::new("a"))), + left: Box::new(Identifier(Ident::new("a").empty_span())), op: Multiply, - right: Box::new(Identifier(Ident::new("b"))), + right: Box::new(Identifier(Ident::new("b").empty_span())), }), op: Plus, - right: Box::new(Identifier(Ident::new("c"))), + right: Box::new(Identifier(Ident::new("c").empty_span())), }, verified_expr(sql) ); @@ -954,12 +965,12 @@ fn parse_unary_math() { BinaryOp { left: Box::new(UnaryOp { op: UnaryOperator::Minus, - expr: Box::new(Identifier(Ident::new("a"))), + expr: Box::new(Identifier(Ident::new("a").empty_span())), }), op: BinaryOperator::Plus, right: Box::new(UnaryOp { op: UnaryOperator::Minus, - expr: Box::new(Identifier(Ident::new("b"))), + expr: Box::new(Identifier(Ident::new("b").empty_span())), }), }, verified_expr(sql) @@ -971,7 +982,7 @@ fn parse_is_null() { use self::Expr::*; let sql = "a IS NULL"; assert_eq!( - IsNull(Box::new(Identifier(Ident::new("a")))), + IsNull(Box::new(Identifier(Ident::new("a").empty_span()))), verified_expr(sql) ); } @@ -981,7 +992,7 @@ fn parse_is_not_null() { use self::Expr::*; let sql = "a IS NOT NULL"; assert_eq!( - IsNotNull(Box::new(Identifier(Ident::new("a")))), + IsNotNull(Box::new(Identifier(Ident::new("a").empty_span()))), verified_expr(sql) ); } @@ -992,8 +1003,8 @@ fn parse_is_distinct_from() { let sql = "a IS DISTINCT FROM b"; assert_eq!( IsDistinctFrom( - Box::new(Identifier(Ident::new("a"))), - Box::new(Identifier(Ident::new("b"))), + Box::new(Identifier(Ident::new("a").empty_span())), + Box::new(Identifier(Ident::new("b").empty_span())), ), verified_expr(sql) ); @@ -1005,8 +1016,8 @@ fn parse_is_not_distinct_from() { let sql = "a IS NOT DISTINCT FROM b"; assert_eq!( IsNotDistinctFrom( - Box::new(Identifier(Ident::new("a"))), - Box::new(Identifier(Ident::new("b"))), + Box::new(Identifier(Ident::new("a").empty_span())), + Box::new(Identifier(Ident::new("b").empty_span())), ), verified_expr(sql) ); @@ -1071,7 +1082,7 @@ fn parse_not_precedence() { Expr::UnaryOp { op: UnaryOperator::Not, expr: Box::new(Expr::InList { - expr: Box::new(Expr::Identifier("a".into())), + expr: Box::new(Expr::Identifier(Ident::new("a").empty_span())), list: vec![Expr::Value(Value::SingleQuotedString("a".into()))], negated: true, }), @@ -1089,7 +1100,7 @@ fn parse_null_like() { assert_eq!( SelectItem::ExprWithAlias { expr: Expr::Like { - expr: Box::new(Expr::Identifier(Ident::new("column1"))), + expr: Box::new(Expr::Identifier(Ident::new("column1").empty_span())), negated: false, pattern: Box::new(Expr::Value(Value::Null)), escape_char: None, @@ -1106,7 +1117,7 @@ fn parse_null_like() { expr: Expr::Like { expr: Box::new(Expr::Value(Value::Null)), negated: false, - pattern: Box::new(Expr::Identifier(Ident::new("column1"))), + pattern: Box::new(Expr::Identifier(Ident::new("column1").empty_span())), escape_char: None, }, alias: Ident { @@ -1128,7 +1139,7 @@ fn parse_ilike() { let select = verified_only_select(sql); assert_eq!( Expr::ILike { - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier(Ident::new("name").empty_span())), negated, pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))), escape_char: None, @@ -1144,7 +1155,7 @@ fn parse_ilike() { let select = verified_only_select(sql); assert_eq!( Expr::ILike { - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier(Ident::new("name").empty_span())), negated, pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))), escape_char: Some('^'), @@ -1161,7 +1172,7 @@ fn parse_ilike() { let select = verified_only_select(sql); assert_eq!( Expr::IsNull(Box::new(Expr::ILike { - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier(Ident::new("name").empty_span())), negated, pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))), escape_char: None, @@ -1183,7 +1194,7 @@ fn parse_in_list() { let select = verified_only_select(sql); assert_eq!( Expr::InList { - expr: Box::new(Expr::Identifier(Ident::new("segment"))), + expr: Box::new(Expr::Identifier(Ident::new("segment").empty_span())), list: vec![ Expr::Value(Value::SingleQuotedString("HIGH".to_string())), Expr::Value(Value::SingleQuotedString("MED".to_string())), @@ -1203,7 +1214,7 @@ fn parse_in_subquery() { let select = verified_only_select(sql); assert_eq!( Expr::InSubquery { - expr: Box::new(Expr::Identifier(Ident::new("segment"))), + expr: Box::new(Expr::Identifier(Ident::new("segment").empty_span())), subquery: Box::new(verified_query("SELECT segm FROM bar")), negated: false, }, @@ -1221,7 +1232,7 @@ fn parse_in_unnest() { let select = verified_only_select(sql); assert_eq!( Expr::InUnnest { - expr: Box::new(Expr::Identifier(Ident::new("segment"))), + expr: Box::new(Expr::Identifier(Ident::new("segment").empty_span())), array_expr: Box::new(verified_expr("expr")), negated, }, @@ -1250,9 +1261,9 @@ fn parse_string_agg() { let select = verified_only_select(sql); assert_eq!( SelectItem::UnnamedExpr(Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident::new("a"))), + left: Box::new(Expr::Identifier(Ident::new("a").empty_span())), op: BinaryOperator::StringConcat, - right: Box::new(Expr::Identifier(Ident::new("b"))), + right: Box::new(Expr::Identifier(Ident::new("b").empty_span())), }), select.projection[0] ); @@ -1281,9 +1292,9 @@ fn parse_bitwise_ops() { let select = dialects.verified_only_select(&format!("SELECT a {} b", &str_op)); assert_eq!( SelectItem::UnnamedExpr(Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident::new("a"))), + left: Box::new(Expr::Identifier(Ident::new("a").spanning(8..9))), op: op.clone(), - right: Box::new(Expr::Identifier(Ident::new("b"))), + right: Box::new(Expr::Identifier(Ident::new("b").spanning(12..13))), }), select.projection[0] ); @@ -1295,9 +1306,11 @@ fn parse_binary_any() { let select = verified_only_select("SELECT a = ANY(b)"); assert_eq!( SelectItem::UnnamedExpr(Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident::new("a"))), + left: Box::new(Expr::Identifier(Ident::new("a").spanning(8..9))), op: BinaryOperator::Eq, - right: Box::new(Expr::AnyOp(Box::new(Expr::Identifier(Ident::new("b"))))), + right: Box::new(Expr::AnyOp(Box::new(Expr::Identifier( + Ident::new("b").spanning(16..17) + )))), }), select.projection[0] ); @@ -1308,9 +1321,11 @@ fn parse_binary_all() { let select = verified_only_select("SELECT a = ALL(b)"); assert_eq!( SelectItem::UnnamedExpr(Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident::new("a"))), + left: Box::new(Expr::Identifier(Ident::new("a").spanning(8..9))), op: BinaryOperator::Eq, - right: Box::new(Expr::AllOp(Box::new(Expr::Identifier(Ident::new("b"))))), + right: Box::new(Expr::AllOp(Box::new(Expr::Identifier( + Ident::new("b").spanning(16..17) + )))), }), select.projection[0] ); @@ -1364,7 +1379,7 @@ fn parse_between() { let select = verified_only_select(sql); assert_eq!( Expr::Between { - expr: Box::new(Expr::Identifier(Ident::new("age"))), + expr: Box::new(Expr::Identifier(Ident::new("age").spanning(31..34))), low: Box::new(Expr::Value(number("25"))), high: Box::new(Expr::Value(number("32"))), negated, @@ -1413,7 +1428,7 @@ fn parse_between_with_expr() { expr: Box::new(Expr::BinaryOp { left: Box::new(Expr::Value(number("1"))), op: BinaryOperator::Plus, - right: Box::new(Expr::Identifier(Ident::new("x"))), + right: Box::new(Expr::Identifier(Ident::new("x").spanning(37..38))), }), low: Box::new(Expr::Value(number("1"))), high: Box::new(Expr::Value(number("2"))), @@ -1438,7 +1453,7 @@ fn parse_tuples() { SelectItem::UnnamedExpr(Expr::Tuple(vec![ Expr::Value(Value::SingleQuotedString("foo".into())), Expr::Value(number("3")), - Expr::Identifier(Ident::new("baz")), + Expr::Identifier(Ident::new("baz").empty_span()), ])), ], select.projection @@ -1469,17 +1484,17 @@ fn parse_select_order_by() { assert_eq!( vec![ OrderByExpr { - expr: Expr::Identifier(Ident::new("lname")), + expr: Expr::Identifier(Ident::new("lname").empty_span()), asc: Some(true), nulls_first: None, }, OrderByExpr { - expr: Expr::Identifier(Ident::new("fname")), + expr: Expr::Identifier(Ident::new("fname").empty_span()), asc: Some(false), nulls_first: None, }, OrderByExpr { - expr: Expr::Identifier(Ident::new("id")), + expr: Expr::Identifier(Ident::new("id").empty_span()), asc: None, nulls_first: None, }, @@ -1501,12 +1516,12 @@ fn parse_select_order_by_limit() { assert_eq!( vec![ OrderByExpr { - expr: Expr::Identifier(Ident::new("lname")), + expr: Expr::Identifier(Ident::new("lname").empty_span()), asc: Some(true), nulls_first: None, }, OrderByExpr { - expr: Expr::Identifier(Ident::new("fname")), + expr: Expr::Identifier(Ident::new("fname").empty_span()), asc: Some(false), nulls_first: None, }, @@ -1524,12 +1539,12 @@ fn parse_select_order_by_nulls_order() { assert_eq!( vec![ OrderByExpr { - expr: Expr::Identifier(Ident::new("lname")), + expr: Expr::Identifier(Ident::new("lname").empty_span()), asc: Some(true), nulls_first: Some(true), }, OrderByExpr { - expr: Expr::Identifier(Ident::new("fname")), + expr: Expr::Identifier(Ident::new("fname").empty_span()), asc: Some(false), nulls_first: Some(false), }, @@ -1545,8 +1560,8 @@ fn parse_select_group_by() { let select = verified_only_select(sql); assert_eq!( vec![ - Expr::Identifier(Ident::new("lname")), - Expr::Identifier(Ident::new("fname")), + Expr::Identifier(Ident::new("lname").empty_span()), + Expr::Identifier(Ident::new("fname").empty_span()), ], select.group_by ); @@ -1568,10 +1583,10 @@ fn parse_select_group_by_grouping_sets() { let select = dialects.verified_only_select(sql); assert_eq!( vec![ - Expr::Identifier(Ident::new("size")), + Expr::Identifier(Ident::new("size").empty_span()), Expr::GroupingSets(vec![ - vec![Expr::Identifier(Ident::new("brand"))], - vec![Expr::Identifier(Ident::new("size"))], + vec![Expr::Identifier(Ident::new("brand").empty_span())], + vec![Expr::Identifier(Ident::new("size").empty_span())], vec![], ]), ], @@ -1588,10 +1603,10 @@ fn parse_select_group_by_rollup() { let select = dialects.verified_only_select(sql); assert_eq!( vec![ - Expr::Identifier(Ident::new("size")), + Expr::Identifier(Ident::new("size").empty_span()), Expr::Rollup(vec![ - vec![Expr::Identifier(Ident::new("brand"))], - vec![Expr::Identifier(Ident::new("size"))], + vec![Expr::Identifier(Ident::new("brand").empty_span())], + vec![Expr::Identifier(Ident::new("size").empty_span())], ]), ], select.group_by @@ -1607,10 +1622,10 @@ fn parse_select_group_by_cube() { let select = dialects.verified_only_select(sql); assert_eq!( vec![ - Expr::Identifier(Ident::new("size")), + Expr::Identifier(Ident::new("size").empty_span()), Expr::Cube(vec![ - vec![Expr::Identifier(Ident::new("brand"))], - vec![Expr::Identifier(Ident::new("size"))], + vec![Expr::Identifier(Ident::new("brand").empty_span())], + vec![Expr::Identifier(Ident::new("size").empty_span())], ]), ], select.group_by @@ -1652,9 +1667,9 @@ fn parse_select_qualify() { name: ObjectName(vec![Ident::new("ROW_NUMBER")]), args: vec![], over: Some(WindowSpec { - partition_by: vec![Expr::Identifier(Ident::new("p"))], + partition_by: vec![Expr::Identifier(Ident::new("p").empty_span())], order_by: vec![OrderByExpr { - expr: Expr::Identifier(Ident::new("o")), + expr: Expr::Identifier(Ident::new("o").empty_span()), asc: None, nulls_first: None, }], @@ -1673,7 +1688,7 @@ fn parse_select_qualify() { let select = verified_only_select(sql); assert_eq!( Some(Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident::new("row_num"))), + left: Box::new(Expr::Identifier(Ident::new("row_num").empty_span())), op: BinaryOperator::Eq, right: Box::new(Expr::Value(number("1"))), }), @@ -1695,7 +1710,7 @@ fn parse_cast() { let select = verified_only_select(sql); assert_eq!( &Expr::Cast { - expr: Box::new(Expr::Identifier(Ident::new("id"))), + expr: Box::new(Expr::Identifier(Ident::new("id").empty_span())), data_type: DataType::BigInt(None), }, expr_from_projection(only(&select.projection)) @@ -1705,7 +1720,7 @@ fn parse_cast() { let select = verified_only_select(sql); assert_eq!( &Expr::Cast { - expr: Box::new(Expr::Identifier(Ident::new("id"))), + expr: Box::new(Expr::Identifier(Ident::new("id").empty_span())), data_type: DataType::TinyInt(None), }, expr_from_projection(only(&select.projection)) @@ -1731,7 +1746,7 @@ fn parse_cast() { let select = verified_only_select(sql); assert_eq!( &Expr::Cast { - expr: Box::new(Expr::Identifier(Ident::new("id"))), + expr: Box::new(Expr::Identifier(Ident::new("id").empty_span())), data_type: DataType::Nvarchar(Some(50)), }, expr_from_projection(only(&select.projection)) @@ -1741,7 +1756,7 @@ fn parse_cast() { let select = verified_only_select(sql); assert_eq!( &Expr::Cast { - expr: Box::new(Expr::Identifier(Ident::new("id"))), + expr: Box::new(Expr::Identifier(Ident::new("id").empty_span())), data_type: DataType::Clob(None), }, expr_from_projection(only(&select.projection)) @@ -1751,7 +1766,7 @@ fn parse_cast() { let select = verified_only_select(sql); assert_eq!( &Expr::Cast { - expr: Box::new(Expr::Identifier(Ident::new("id"))), + expr: Box::new(Expr::Identifier(Ident::new("id").empty_span())), data_type: DataType::Clob(Some(50)), }, expr_from_projection(only(&select.projection)) @@ -1761,7 +1776,7 @@ fn parse_cast() { let select = verified_only_select(sql); assert_eq!( &Expr::Cast { - expr: Box::new(Expr::Identifier(Ident::new("id"))), + expr: Box::new(Expr::Identifier(Ident::new("id").empty_span())), data_type: DataType::Binary(Some(50)), }, expr_from_projection(only(&select.projection)) @@ -1771,7 +1786,7 @@ fn parse_cast() { let select = verified_only_select(sql); assert_eq!( &Expr::Cast { - expr: Box::new(Expr::Identifier(Ident::new("id"))), + expr: Box::new(Expr::Identifier(Ident::new("id").empty_span())), data_type: DataType::Varbinary(Some(50)), }, expr_from_projection(only(&select.projection)) @@ -1781,7 +1796,7 @@ fn parse_cast() { let select = verified_only_select(sql); assert_eq!( &Expr::Cast { - expr: Box::new(Expr::Identifier(Ident::new("id"))), + expr: Box::new(Expr::Identifier(Ident::new("id").empty_span())), data_type: DataType::Blob(None), }, expr_from_projection(only(&select.projection)) @@ -1791,7 +1806,7 @@ fn parse_cast() { let select = verified_only_select(sql); assert_eq!( &Expr::Cast { - expr: Box::new(Expr::Identifier(Ident::new("id"))), + expr: Box::new(Expr::Identifier(Ident::new("id").empty_span())), data_type: DataType::Blob(Some(50)), }, expr_from_projection(only(&select.projection)) @@ -1804,7 +1819,7 @@ fn parse_try_cast() { let select = verified_only_select(sql); assert_eq!( &Expr::TryCast { - expr: Box::new(Expr::Identifier(Ident::new("id"))), + expr: Box::new(Expr::Identifier(Ident::new("id").empty_span())), data_type: DataType::BigInt(None), }, expr_from_projection(only(&select.projection)) @@ -1825,7 +1840,7 @@ fn parse_extract() { assert_eq!( &Expr::Extract { field: DateTimeField::Year, - expr: Box::new(Expr::Identifier(Ident::new("d"))), + expr: Box::new(Expr::Identifier(Ident::new("d").empty_span())), }, expr_from_projection(only(&select.projection)), ); @@ -1886,7 +1901,7 @@ fn parse_ceil_datetime() { let select = verified_only_select(sql); assert_eq!( &Expr::Ceil { - expr: Box::new(Expr::Identifier(Ident::new("d"))), + expr: Box::new(Expr::Identifier(Ident::new("d").empty_span())), field: DateTimeField::Day, }, expr_from_projection(only(&select.projection)), @@ -1912,7 +1927,7 @@ fn parse_floor_datetime() { let select = verified_only_select(sql); assert_eq!( &Expr::Floor { - expr: Box::new(Expr::Identifier(Ident::new("d"))), + expr: Box::new(Expr::Identifier(Ident::new("d").empty_span())), field: DateTimeField::Day, }, expr_from_projection(only(&select.projection)), @@ -1945,7 +1960,7 @@ fn parse_listagg() { verified_stmt("SELECT LISTAGG(dateid ON OVERFLOW TRUNCATE N'...' WITH COUNT)"); verified_stmt("SELECT LISTAGG(dateid ON OVERFLOW TRUNCATE X'deadbeef' WITH COUNT)"); - let expr = Box::new(Expr::Identifier(Ident::new("dateid"))); + let expr = Box::new(Expr::Identifier(Ident::new("dateid").empty_span())); let on_overflow = Some(ListAggOnOverflow::Truncate { filler: Some(Box::new(Expr::Value(Value::SingleQuotedString( "%".to_string(), @@ -1954,18 +1969,24 @@ fn parse_listagg() { }); let within_group = vec![ OrderByExpr { - expr: Expr::Identifier(Ident { - value: "id".to_string(), - quote_style: None, - }), + expr: Expr::Identifier( + Ident { + value: "id".to_string(), + quote_style: None, + } + .empty_span(), + ), asc: None, nulls_first: None, }, OrderByExpr { - expr: Expr::Identifier(Ident { - value: "username".to_string(), - quote_style: None, - }), + expr: Expr::Identifier( + Ident { + value: "username".to_string(), + quote_style: None, + } + .empty_span(), + ), asc: None, nulls_first: None, }, @@ -3041,7 +3062,7 @@ fn parse_scalar_function_in_projection() { &Expr::Function(Function { name: ObjectName(vec![Ident::new(function_name)]), args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr( - Expr::Identifier(Ident::new("id")) + Expr::Identifier(Ident::new("id").empty_span()) ))], over: None, distinct: false, @@ -3194,7 +3215,7 @@ fn parse_window_functions() { over: Some(WindowSpec { partition_by: vec![], order_by: vec![OrderByExpr { - expr: Expr::Identifier(Ident::new("dt")), + expr: Expr::Identifier(Ident::new("dt").empty_span()), asc: Some(false), nulls_first: None, }], @@ -3482,10 +3503,13 @@ fn parse_interval_and_or_xor() { body: Box::new(SetExpr::Select(Box::new(Select { distinct: false, top: None, - projection: vec![UnnamedExpr(Expr::Identifier(Ident { - value: "col".to_string(), - quote_style: None, - }))], + projection: vec![UnnamedExpr(Expr::Identifier( + Ident { + value: "col".to_string(), + quote_style: None, + } + .empty_span(), + ))], into: None, from: vec![TableWithJoins { relation: TableFactor::Table { @@ -3502,16 +3526,22 @@ fn parse_interval_and_or_xor() { lateral_views: vec![], selection: Some(Expr::BinaryOp { left: Box::new(Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident { - value: "d3_date".to_string(), - quote_style: None, - })), + left: Box::new(Expr::Identifier( + Ident { + value: "d3_date".to_string(), + quote_style: None, + } + .empty_span(), + )), op: BinaryOperator::Gt, right: Box::new(Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident { - value: "d1_date".to_string(), - quote_style: None, - })), + left: Box::new(Expr::Identifier( + Ident { + value: "d1_date".to_string(), + quote_style: None, + } + .empty_span(), + )), op: BinaryOperator::Plus, right: Box::new(Expr::Interval { value: Box::new(Expr::Value(Value::SingleQuotedString( @@ -3526,16 +3556,22 @@ fn parse_interval_and_or_xor() { }), op: BinaryOperator::And, right: Box::new(Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident { - value: "d2_date".to_string(), - quote_style: None, - })), + left: Box::new(Expr::Identifier( + Ident { + value: "d2_date".to_string(), + quote_style: None, + } + .empty_span(), + )), op: BinaryOperator::Gt, right: Box::new(Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident { - value: "d1_date".to_string(), - quote_style: None, - })), + left: Box::new(Expr::Identifier( + Ident { + value: "d1_date".to_string(), + quote_style: None, + } + .empty_span(), + )), op: BinaryOperator::Plus, right: Box::new(Expr::Interval { value: Box::new(Expr::Value(Value::SingleQuotedString( @@ -3850,7 +3886,7 @@ fn parse_unnest() { name: Ident::new("numbers"), columns: vec![], }), - array_expr: Box::new(Expr::Identifier(Ident::new("expr"))), + array_expr: Box::new(Expr::Identifier(Ident::new("expr").empty_span())), with_offset: true, with_offset_alias: None, }, @@ -3866,7 +3902,7 @@ fn parse_unnest() { vec![TableWithJoins { relation: TableFactor::UNNEST { alias: None, - array_expr: Box::new(Expr::Identifier(Ident::new("expr"))), + array_expr: Box::new(Expr::Identifier(Ident::new("expr").empty_span())), with_offset: false, with_offset_alias: None, }, @@ -3882,7 +3918,7 @@ fn parse_unnest() { vec![TableWithJoins { relation: TableFactor::UNNEST { alias: None, - array_expr: Box::new(Expr::Identifier(Ident::new("expr"))), + array_expr: Box::new(Expr::Identifier(Ident::new("expr").empty_span())), with_offset: true, with_offset_alias: None, }, @@ -3901,7 +3937,7 @@ fn parse_unnest() { name: Ident::new("numbers"), columns: vec![], }), - array_expr: Box::new(Expr::Identifier(Ident::new("expr"))), + array_expr: Box::new(Expr::Identifier(Ident::new("expr").empty_span())), with_offset: false, with_offset_alias: None, }, @@ -3918,15 +3954,15 @@ fn parse_parens() { assert_eq!( BinaryOp { left: Box::new(Nested(Box::new(BinaryOp { - left: Box::new(Identifier(Ident::new("a"))), + left: Box::new(Identifier(Ident::new("a").empty_span())), op: Plus, - right: Box::new(Identifier(Ident::new("b"))), + right: Box::new(Identifier(Ident::new("b").empty_span())), }))), op: Minus, right: Box::new(Nested(Box::new(BinaryOp { - left: Box::new(Identifier(Ident::new("c"))), + left: Box::new(Identifier(Ident::new("c").empty_span())), op: Plus, - right: Box::new(Identifier(Ident::new("d"))), + right: Box::new(Identifier(Ident::new("d").empty_span())), }))), }, verified_expr(sql) @@ -3943,14 +3979,14 @@ fn parse_searched_case_expr() { &Case { operand: None, conditions: vec![ - IsNull(Box::new(Identifier(Ident::new("bar")))), + IsNull(Box::new(Identifier(Ident::new("bar").empty_span()))), BinaryOp { - left: Box::new(Identifier(Ident::new("bar"))), + left: Box::new(Identifier(Ident::new("bar").empty_span())), op: Eq, right: Box::new(Expr::Value(number("0"))), }, BinaryOp { - left: Box::new(Identifier(Ident::new("bar"))), + left: Box::new(Identifier(Ident::new("bar").empty_span())), op: GtEq, right: Box::new(Expr::Value(number("0"))), }, @@ -3976,7 +4012,7 @@ fn parse_simple_case_expr() { use self::Expr::{Case, Identifier}; assert_eq!( &Case { - operand: Some(Box::new(Identifier(Ident::new("foo")))), + operand: Some(Box::new(Identifier(Ident::new("foo").empty_span()))), conditions: vec![Expr::Value(number("1"))], results: vec![Expr::Value(Value::SingleQuotedString("Y".to_string()))], else_result: Some(Box::new(Expr::Value(Value::SingleQuotedString( @@ -4103,9 +4139,9 @@ fn parse_joins_on() { with_hints: vec![], }, join_operator: f(JoinConstraint::On(Expr::BinaryOp { - left: Box::new(Expr::Identifier("c1".into())), + left: Box::new(Expr::Identifier(Ident::new("c1").empty_span())), op: BinaryOperator::Eq, - right: Box::new(Expr::Identifier("c2".into())), + right: Box::new(Expr::Identifier(Ident::new("c2").empty_span())), })), } } @@ -4624,10 +4660,10 @@ fn parse_overlay() { assert_eq!( &Expr::Overlay { expr: Box::new(Expr::Value(Value::SingleQuotedString("abcdef".to_string()))), - overlay_what: Box::new(Expr::Identifier(Ident::new("name"))), + overlay_what: Box::new(Expr::Identifier(Ident::new("name").empty_span())), overlay_from: Box::new(Expr::Value(number("3"))), overlay_for: Some(Box::new(Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident::new("id"))), + left: Box::new(Expr::Identifier(Ident::new("id").empty_span())), op: BinaryOperator::Plus, right: Box::new(Expr::Value(number("1"))), })), @@ -5444,12 +5480,12 @@ fn parse_create_index() { let sql = "CREATE UNIQUE INDEX IF NOT EXISTS idx_name ON test(name,age DESC)"; let indexed_columns = vec![ OrderByExpr { - expr: Expr::Identifier(Ident::new("name")), + expr: Expr::Identifier(Ident::new("name").empty_span()), asc: None, nulls_first: None, }, OrderByExpr { - expr: Expr::Identifier(Ident::new("age")), + expr: Expr::Identifier(Ident::new("age").empty_span()), asc: Some(false), nulls_first: None, }, @@ -5478,12 +5514,12 @@ fn test_create_index_with_using_function() { let sql = "CREATE UNIQUE INDEX IF NOT EXISTS idx_name ON test USING btree (name,age DESC)"; let indexed_columns = vec![ OrderByExpr { - expr: Expr::Identifier(Ident::new("name")), + expr: Expr::Identifier(Ident::new("name").empty_span()), asc: None, nulls_first: None, }, OrderByExpr { - expr: Expr::Identifier(Ident::new("age")), + expr: Expr::Identifier(Ident::new("age").empty_span()), asc: Some(false), nulls_first: None, }, @@ -6059,7 +6095,7 @@ fn test_placeholder() { assert_eq!( ast.selection, Some(Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident::new("id"))), + left: Box::new(Expr::Identifier(Ident::new("id").empty_span())), op: BinaryOperator::Eq, right: Box::new(Expr::Value(Value::Placeholder("?".into()))), }) @@ -6082,7 +6118,7 @@ fn test_placeholder() { assert_eq!( ast.selection, Some(Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident::new("id"))), + left: Box::new(Expr::Identifier(Ident::new("id").empty_span())), op: BinaryOperator::Eq, right: Box::new(Expr::Value(Value::Placeholder("$Id1".into()))), }) @@ -6146,6 +6182,26 @@ fn verified_expr(query: &str) -> Expr { all_dialects().verified_expr(query) } +#[test] +fn parse_identifiers() { + let sql = "SELECT foo AS baz FROM bar"; + let ast = verified_query(sql); + match *ast.body { + SetExpr::Select(select) => { + let select: Select = *select; + dbg!(&select.projection); + assert_eq!( + select.projection, + vec![SelectItem::ExprWithAlias { + expr: Expr::Identifier(Ident::new("foo").spanning(Span::new((1, 8), (1, 11)))), + alias: Ident::new("baz") + }] + ) + } + _ => {} + }; +} + #[test] fn parse_offset_and_limit() { let sql = "SELECT foo FROM bar LIMIT 2 OFFSET 2"; @@ -6293,7 +6349,7 @@ fn parse_position() { assert_eq!( &Expr::Position { expr: Box::new(Expr::Value(Value::SingleQuotedString("@".to_string()))), - r#in: Box::new(Expr::Identifier(Ident::new("field"))), + r#in: Box::new(Expr::Identifier(Ident::new("field").empty_span())), }, expr_from_projection(only(&select.projection)) ); @@ -6322,37 +6378,37 @@ fn parse_is_boolean() { let sql = "a IS TRUE"; assert_eq!( - IsTrue(Box::new(Identifier(Ident::new("a")))), + IsTrue(Box::new(Identifier(Ident::new("a").empty_span()))), verified_expr(sql) ); let sql = "a IS NOT TRUE"; assert_eq!( - IsNotTrue(Box::new(Identifier(Ident::new("a")))), + IsNotTrue(Box::new(Identifier(Ident::new("a").empty_span()))), verified_expr(sql) ); let sql = "a IS FALSE"; assert_eq!( - IsFalse(Box::new(Identifier(Ident::new("a")))), + IsFalse(Box::new(Identifier(Ident::new("a").empty_span()))), verified_expr(sql) ); let sql = "a IS NOT FALSE"; assert_eq!( - IsNotFalse(Box::new(Identifier(Ident::new("a")))), + IsNotFalse(Box::new(Identifier(Ident::new("a").empty_span()))), verified_expr(sql) ); let sql = "a IS UNKNOWN"; assert_eq!( - IsUnknown(Box::new(Identifier(Ident::new("a")))), + IsUnknown(Box::new(Identifier(Ident::new("a").empty_span()))), verified_expr(sql) ); let sql = "a IS NOT UNKNOWN"; assert_eq!( - IsNotUnknown(Box::new(Identifier(Ident::new("a")))), + IsNotUnknown(Box::new(Identifier(Ident::new("a").empty_span()))), verified_expr(sql) ); diff --git a/tests/sqlparser_hive.rs b/tests/sqlparser_hive.rs index 064a090f7..dc5e56b4b 100644 --- a/tests/sqlparser_hive.rs +++ b/tests/sqlparser_hive.rs @@ -17,7 +17,7 @@ use sqlparser::ast::{ CreateFunctionBody, CreateFunctionUsing, Expr, Function, FunctionDefinition, Ident, ObjectName, - SelectItem, Statement, TableFactor, UnaryOperator, Value, + SelectItem, SpanWrapped, Statement, TableFactor, UnaryOperator, Value, }; use sqlparser::dialect::{GenericDialect, HiveDialect}; use sqlparser::parser::ParserError; @@ -224,7 +224,7 @@ fn set_statement_with_minus() { ]), value: vec![Expr::UnaryOp { op: UnaryOperator::Minus, - expr: Box::new(Expr::Identifier(Ident::new("Xmx4g"))) + expr: Box::new(Expr::Identifier(Ident::new("Xmx4g").empty_span())) }], } ); @@ -350,7 +350,10 @@ fn parse_delimited_identifiers() { ); match &select.projection[2] { SelectItem::ExprWithAlias { expr, alias } => { - assert_eq!(&Expr::Identifier(Ident::with_quote('"', "simple id")), expr); + assert_eq!( + &Expr::Identifier(Ident::with_quote('"', "simple id").empty_span()), + expr + ); assert_eq!(&Ident::with_quote('"', "column alias"), alias); } _ => panic!("Expected ExprWithAlias"), @@ -371,7 +374,7 @@ fn parse_like() { let select = hive().verified_only_select(sql); assert_eq!( Expr::Like { - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier(Ident::new("name").empty_span())), negated, pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))), escape_char: None, @@ -387,7 +390,7 @@ fn parse_like() { let select = hive().verified_only_select(sql); assert_eq!( Expr::Like { - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier(Ident::new("name").empty_span())), negated, pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))), escape_char: Some('\\'), @@ -404,7 +407,7 @@ fn parse_like() { let select = hive().verified_only_select(sql); assert_eq!( Expr::IsNull(Box::new(Expr::Like { - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier(Ident::new("name").empty_span())), negated, pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))), escape_char: None, @@ -426,7 +429,7 @@ fn parse_similar_to() { let select = hive().verified_only_select(sql); assert_eq!( Expr::SimilarTo { - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier(Ident::new("name").empty_span())), negated, pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))), escape_char: None, @@ -442,7 +445,7 @@ fn parse_similar_to() { let select = hive().verified_only_select(sql); assert_eq!( Expr::SimilarTo { - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier(Ident::new("name").empty_span())), negated, pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))), escape_char: Some('\\'), @@ -458,7 +461,7 @@ fn parse_similar_to() { let select = hive().verified_only_select(sql); assert_eq!( Expr::IsNull(Box::new(Expr::SimilarTo { - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier(Ident::new("name").empty_span())), negated, pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))), escape_char: Some('\\'), diff --git a/tests/sqlparser_mssql.rs b/tests/sqlparser_mssql.rs index 41b0803e4..58aaf802e 100644 --- a/tests/sqlparser_mssql.rs +++ b/tests/sqlparser_mssql.rs @@ -26,11 +26,11 @@ fn parse_mssql_identifiers() { let sql = "SELECT @@version, _foo$123 FROM ##temp"; let select = ms_and_generic().verified_only_select(sql); assert_eq!( - &Expr::Identifier(Ident::new("@@version")), + &Expr::Identifier(Ident::new("@@version").empty_span()), expr_from_projection(&select.projection[0]), ); assert_eq!( - &Expr::Identifier(Ident::new("_foo$123")), + &Expr::Identifier(Ident::new("_foo$123").empty_span()), expr_from_projection(&select.projection[1]), ); assert_eq!(2, select.projection.len()); @@ -182,7 +182,10 @@ fn parse_delimited_identifiers() { ); match &select.projection[2] { SelectItem::ExprWithAlias { expr, alias } => { - assert_eq!(&Expr::Identifier(Ident::with_quote('"', "simple id")), expr); + assert_eq!( + &Expr::Identifier(Ident::with_quote('"', "simple id").empty_span()), + expr + ); assert_eq!(&Ident::with_quote('"', "column alias"), alias); } _ => panic!("Expected ExprWithAlias"), @@ -203,7 +206,7 @@ fn parse_like() { let select = ms_and_generic().verified_only_select(sql); assert_eq!( Expr::Like { - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier(Ident::new("name").empty_span())), negated, pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))), escape_char: None, @@ -219,7 +222,7 @@ fn parse_like() { let select = ms_and_generic().verified_only_select(sql); assert_eq!( Expr::Like { - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier(Ident::new("name").empty_span())), negated, pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))), escape_char: Some('\\'), @@ -236,7 +239,7 @@ fn parse_like() { let select = ms_and_generic().verified_only_select(sql); assert_eq!( Expr::IsNull(Box::new(Expr::Like { - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier(Ident::new("name").empty_span())), negated, pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))), escape_char: None, @@ -258,7 +261,7 @@ fn parse_similar_to() { let select = ms_and_generic().verified_only_select(sql); assert_eq!( Expr::SimilarTo { - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier(Ident::new("name").empty_span())), negated, pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))), escape_char: None, @@ -274,7 +277,7 @@ fn parse_similar_to() { let select = ms_and_generic().verified_only_select(sql); assert_eq!( Expr::SimilarTo { - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier(Ident::new("name").empty_span())), negated, pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))), escape_char: Some('\\'), @@ -290,7 +293,7 @@ fn parse_similar_to() { let select = ms_and_generic().verified_only_select(sql); assert_eq!( Expr::IsNull(Box::new(Expr::SimilarTo { - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier(Ident::new("name").empty_span())), negated, pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))), escape_char: Some('\\'), diff --git a/tests/sqlparser_mysql.rs b/tests/sqlparser_mysql.rs index 04c86cb15..9ff80f25d 100644 --- a/tests/sqlparser_mysql.rs +++ b/tests/sqlparser_mysql.rs @@ -447,10 +447,13 @@ fn parse_quote_identifiers_2() { body: Box::new(SetExpr::Select(Box::new(Select { distinct: false, top: None, - projection: vec![SelectItem::UnnamedExpr(Expr::Identifier(Ident { - value: "quoted ` identifier".into(), - quote_style: Some('`'), - }))], + projection: vec![SelectItem::UnnamedExpr(Expr::Identifier( + Ident { + value: "quoted ` identifier".into(), + quote_style: Some('`'), + } + .empty_span() + ))], into: None, from: vec![], lateral_views: vec![], @@ -481,10 +484,13 @@ fn parse_quote_identifiers_3() { body: Box::new(SetExpr::Select(Box::new(Select { distinct: false, top: None, - projection: vec![SelectItem::UnnamedExpr(Expr::Identifier(Ident { - value: "`quoted identifier`".into(), - quote_style: Some('`'), - }))], + projection: vec![SelectItem::UnnamedExpr(Expr::Identifier( + Ident { + value: "`quoted identifier`".into(), + quote_style: Some('`'), + } + .empty_span() + ))], into: None, from: vec![], lateral_views: vec![], @@ -787,7 +793,7 @@ fn parse_insert_with_on_duplicate_update() { value: Expr::Function(Function { name: ObjectName(vec![Ident::new("VALUES".to_string()),]), args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr( - Expr::Identifier(Ident::new("description")) + Expr::Identifier(Ident::new("description").empty_span()) ))], over: None, distinct: false, @@ -799,7 +805,7 @@ fn parse_insert_with_on_duplicate_update() { value: Expr::Function(Function { name: ObjectName(vec![Ident::new("VALUES".to_string()),]), args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr( - Expr::Identifier(Ident::new("perm_create")) + Expr::Identifier(Ident::new("perm_create").empty_span()) ))], over: None, distinct: false, @@ -811,7 +817,7 @@ fn parse_insert_with_on_duplicate_update() { value: Expr::Function(Function { name: ObjectName(vec![Ident::new("VALUES".to_string()),]), args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr( - Expr::Identifier(Ident::new("perm_read")) + Expr::Identifier(Ident::new("perm_read").empty_span()) ))], over: None, distinct: false, @@ -823,7 +829,7 @@ fn parse_insert_with_on_duplicate_update() { value: Expr::Function(Function { name: ObjectName(vec![Ident::new("VALUES".to_string()),]), args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr( - Expr::Identifier(Ident::new("perm_update")) + Expr::Identifier(Ident::new("perm_update").empty_span()) ))], over: None, distinct: false, @@ -835,7 +841,7 @@ fn parse_insert_with_on_duplicate_update() { value: Expr::Function(Function { name: ObjectName(vec![Ident::new("VALUES".to_string()),]), args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr( - Expr::Identifier(Ident::new("perm_delete")) + Expr::Identifier(Ident::new("perm_delete").empty_span()) ))], over: None, distinct: false, @@ -979,10 +985,13 @@ fn parse_substring_in_select() { distinct: true, top: None, projection: vec![SelectItem::UnnamedExpr(Expr::Substring { - expr: Box::new(Expr::Identifier(Ident { - value: "description".to_string(), - quote_style: None - })), + expr: Box::new(Expr::Identifier( + Ident { + value: "description".to_string(), + quote_style: None + } + .empty_span() + )), substring_from: Some(Box::new(Expr::Value(Value::Number( "0".to_string(), false diff --git a/tests/sqlparser_postgres.rs b/tests/sqlparser_postgres.rs index 359889aac..d00e88698 100644 --- a/tests/sqlparser_postgres.rs +++ b/tests/sqlparser_postgres.rs @@ -986,10 +986,13 @@ fn parse_set() { local: false, hivevar: false, variable: ObjectName(vec![Ident::new("a")]), - value: vec![Expr::Identifier(Ident { - value: "b".into(), - quote_style: None - })], + value: vec![Expr::Identifier( + Ident { + value: "b".into(), + quote_style: None + } + .empty_span() + )], } ); @@ -1028,10 +1031,13 @@ fn parse_set() { local: false, hivevar: false, variable: ObjectName(vec![Ident::new("a")]), - value: vec![Expr::Identifier(Ident { - value: "DEFAULT".into(), - quote_style: None - })], + value: vec![Expr::Identifier( + Ident { + value: "DEFAULT".into(), + quote_style: None + } + .empty_span() + )], } ); @@ -1042,7 +1048,7 @@ fn parse_set() { local: true, hivevar: false, variable: ObjectName(vec![Ident::new("a")]), - value: vec![Expr::Identifier("b".into())], + value: vec![Expr::Identifier(Ident::new("b").empty_span())], } ); @@ -1053,10 +1059,13 @@ fn parse_set() { local: false, hivevar: false, variable: ObjectName(vec![Ident::new("a"), Ident::new("b"), Ident::new("c")]), - value: vec![Expr::Identifier(Ident { - value: "b".into(), - quote_style: None - })], + value: vec![Expr::Identifier( + Ident { + value: "b".into(), + quote_style: None + } + .empty_span() + )], } ); @@ -1258,9 +1267,9 @@ fn parse_prepare() { assert!(columns.is_empty()); let expected_values = [vec![ - Expr::Identifier("a1".into()), - Expr::Identifier("a2".into()), - Expr::Identifier("a3".into()), + Expr::Identifier(Ident::new("a1").empty_span()), + Expr::Identifier(Ident::new("a2").empty_span()), + Expr::Identifier(Ident::new("a3").empty_span()), ]]; match &*source.body { SetExpr::Values(Values { rows, .. }) => { @@ -1409,10 +1418,13 @@ fn parse_pg_on_conflict() { value: Expr::Value(Value::Placeholder("$1".to_string())) },], selection: Some(Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident { - value: "dsize".to_string(), - quote_style: None - })), + left: Box::new(Expr::Identifier( + Ident { + value: "dsize".to_string(), + quote_style: None + } + .empty_span() + )), op: BinaryOperator::Gt, right: Box::new(Expr::Value(Value::Placeholder("$2".to_string()))) }) @@ -1446,10 +1458,13 @@ fn parse_pg_on_conflict() { value: Expr::Value(Value::Placeholder("$1".to_string())) },], selection: Some(Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident { - value: "dsize".to_string(), - quote_style: None - })), + left: Box::new(Expr::Identifier( + Ident { + value: "dsize".to_string(), + quote_style: None + } + .empty_span() + )), op: BinaryOperator::Gt, right: Box::new(Expr::Value(Value::Placeholder("$2".to_string()))) }) @@ -1470,7 +1485,7 @@ fn parse_pg_returning() { Statement::Insert { returning, .. } => { assert_eq!( Some(vec![SelectItem::UnnamedExpr(Expr::Identifier( - "did".into() + Ident::new("did").empty_span() )),]), returning ); @@ -1488,14 +1503,14 @@ fn parse_pg_returning() { assert_eq!( Some(vec![ SelectItem::ExprWithAlias { - expr: Expr::Identifier("temp_lo".into()), + expr: Expr::Identifier(Ident::new("temp_lo").empty_span()), alias: "lo".into() }, SelectItem::ExprWithAlias { - expr: Expr::Identifier("temp_hi".into()), + expr: Expr::Identifier(Ident::new("temp_hi").empty_span()), alias: "hi".into() }, - SelectItem::UnnamedExpr(Expr::Identifier("prcp".into())), + SelectItem::UnnamedExpr(Expr::Identifier(Ident::new("prcp").empty_span())), ]), returning ); @@ -1531,9 +1546,9 @@ fn parse_pg_binary_ops() { let select = dialects.verified_only_select(&format!("SELECT a {} b", &str_op)); assert_eq!( SelectItem::UnnamedExpr(Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident::new("a"))), + left: Box::new(Expr::Identifier(Ident::new("a").empty_span())), op: op.clone(), - right: Box::new(Expr::Identifier(Ident::new("b"))), + right: Box::new(Expr::Identifier(Ident::new("b").empty_span())), }), select.projection[0] ); @@ -1555,7 +1570,7 @@ fn parse_pg_unary_ops() { assert_eq!( SelectItem::UnnamedExpr(Expr::UnaryOp { op: *op, - expr: Box::new(Expr::Identifier(Ident::new("a"))), + expr: Box::new(Expr::Identifier(Ident::new("a").empty_span())), }), select.projection[0] ); @@ -1571,7 +1586,7 @@ fn parse_pg_postfix_factorial() { assert_eq!( SelectItem::UnnamedExpr(Expr::UnaryOp { op: *op, - expr: Box::new(Expr::Identifier(Ident::new("a"))), + expr: Box::new(Expr::Identifier(Ident::new("a").empty_span())), }), select.projection[0] ); @@ -1615,7 +1630,7 @@ fn parse_array_index_expr() { let select = pg_and_generic().verified_only_select(sql); assert_eq!( &Expr::ArrayIndex { - obj: Box::new(Expr::Identifier(Ident::new("foo"))), + obj: Box::new(Expr::Identifier(Ident::new("foo").empty_span())), indexes: vec![num[0].clone()], }, expr_from_projection(only(&select.projection)), @@ -1625,7 +1640,7 @@ fn parse_array_index_expr() { let select = pg_and_generic().verified_only_select(sql); assert_eq!( &Expr::ArrayIndex { - obj: Box::new(Expr::Identifier(Ident::new("foo"))), + obj: Box::new(Expr::Identifier(Ident::new("foo").empty_span())), indexes: vec![num[0].clone(), num[0].clone()], }, expr_from_projection(only(&select.projection)), @@ -1635,17 +1650,23 @@ fn parse_array_index_expr() { let select = pg_and_generic().verified_only_select(sql); assert_eq!( &Expr::ArrayIndex { - obj: Box::new(Expr::Identifier(Ident::new("bar"))), + obj: Box::new(Expr::Identifier(Ident::new("bar").empty_span())), indexes: vec![ num[0].clone(), - Expr::Identifier(Ident { - value: "baz".to_string(), - quote_style: Some('"') - }), - Expr::Identifier(Ident { - value: "fooz".to_string(), - quote_style: Some('"') - }) + Expr::Identifier( + Ident { + value: "baz".to_string(), + quote_style: Some('"') + } + .empty_span() + ), + Expr::Identifier( + Ident { + value: "fooz".to_string(), + quote_style: Some('"') + } + .empty_span() + ) ], }, expr_from_projection(only(&select.projection)), @@ -1788,7 +1809,7 @@ fn test_json() { let select = pg().verified_only_select(sql); assert_eq!( SelectItem::UnnamedExpr(Expr::JsonAccess { - left: Box::new(Expr::Identifier(Ident::new("params"))), + left: Box::new(Expr::Identifier(Ident::new("params").empty_span())), operator: JsonOperator::LongArrow, right: Box::new(Expr::Value(Value::SingleQuotedString("name".to_string()))), }), @@ -1799,7 +1820,7 @@ fn test_json() { let select = pg().verified_only_select(sql); assert_eq!( SelectItem::UnnamedExpr(Expr::JsonAccess { - left: Box::new(Expr::Identifier(Ident::new("params"))), + left: Box::new(Expr::Identifier(Ident::new("params").empty_span())), operator: JsonOperator::Arrow, right: Box::new(Expr::Value(Value::SingleQuotedString("name".to_string()))), }), @@ -1810,7 +1831,7 @@ fn test_json() { let select = pg().verified_only_select(sql); assert_eq!( SelectItem::UnnamedExpr(Expr::JsonAccess { - left: Box::new(Expr::Identifier(Ident::new("info"))), + left: Box::new(Expr::Identifier(Ident::new("info").empty_span())), operator: JsonOperator::Arrow, right: Box::new(Expr::JsonAccess { left: Box::new(Expr::Value(Value::SingleQuotedString("items".to_string()))), @@ -1827,7 +1848,7 @@ fn test_json() { let select = pg().verified_only_select(sql); assert_eq!( SelectItem::UnnamedExpr(Expr::JsonAccess { - left: Box::new(Expr::Identifier(Ident::new("info"))), + left: Box::new(Expr::Identifier(Ident::new("info").empty_span())), operator: JsonOperator::HashArrow, right: Box::new(Expr::Value(Value::SingleQuotedString( "{a,b,c}".to_string() @@ -1840,7 +1861,7 @@ fn test_json() { let select = pg().verified_only_select(sql); assert_eq!( SelectItem::UnnamedExpr(Expr::JsonAccess { - left: Box::new(Expr::Identifier(Ident::new("info"))), + left: Box::new(Expr::Identifier(Ident::new("info").empty_span())), operator: JsonOperator::HashLongArrow, right: Box::new(Expr::Value(Value::SingleQuotedString( "{a,b,c}".to_string() @@ -1853,7 +1874,7 @@ fn test_json() { let select = pg().verified_only_select(sql); assert_eq!( Expr::JsonAccess { - left: Box::new(Expr::Identifier(Ident::new("info"))), + left: Box::new(Expr::Identifier(Ident::new("info").empty_span())), operator: JsonOperator::AtArrow, right: Box::new(Expr::Value(Value::SingleQuotedString( "{\"a\": 1}".to_string() @@ -1870,7 +1891,7 @@ fn test_json() { "{\"a\": 1}".to_string() ))), operator: JsonOperator::ArrowAt, - right: Box::new(Expr::Identifier(Ident::new("info"))), + right: Box::new(Expr::Identifier(Ident::new("info").empty_span())), }, select.selection.unwrap(), ); @@ -1879,7 +1900,7 @@ fn test_json() { let select = pg().verified_only_select(sql); assert_eq!( SelectItem::UnnamedExpr(Expr::JsonAccess { - left: Box::new(Expr::Identifier(Ident::from("info"))), + left: Box::new(Expr::Identifier(Ident::from("info").empty_span())), operator: JsonOperator::HashMinus, right: Box::new(Expr::Array(Array { elem: vec![ @@ -1896,7 +1917,7 @@ fn test_json() { let select = pg().verified_only_select(sql); assert_eq!( Expr::JsonAccess { - left: Box::new(Expr::Identifier(Ident::from("info"))), + left: Box::new(Expr::Identifier(Ident::from("info").empty_span())), operator: JsonOperator::AtQuestion, right: Box::new(Expr::Value(Value::SingleQuotedString("$.a".to_string())),), }, @@ -1907,7 +1928,7 @@ fn test_json() { let select = pg().verified_only_select(sql); assert_eq!( Expr::JsonAccess { - left: Box::new(Expr::Identifier(Ident::from("info"))), + left: Box::new(Expr::Identifier(Ident::from("info").empty_span())), operator: JsonOperator::AtAt, right: Box::new(Expr::Value(Value::SingleQuotedString("$.a".to_string())),), }, @@ -2197,10 +2218,13 @@ fn parse_custom_operator() { assert_eq!( select.selection, Some(Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident { - value: "relname".into(), - quote_style: None, - })), + left: Box::new(Expr::Identifier( + Ident { + value: "relname".into(), + quote_style: None, + } + .empty_span() + )), op: BinaryOperator::PGCustomBinaryOperator(vec![ "database".into(), "pg_catalog".into(), @@ -2216,10 +2240,13 @@ fn parse_custom_operator() { assert_eq!( select.selection, Some(Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident { - value: "relname".into(), - quote_style: None, - })), + left: Box::new(Expr::Identifier( + Ident { + value: "relname".into(), + quote_style: None, + } + .empty_span() + )), op: BinaryOperator::PGCustomBinaryOperator(vec!["pg_catalog".into(), "~".into()]), right: Box::new(Expr::Value(Value::SingleQuotedString("^(table)$".into()))) }) @@ -2231,10 +2258,13 @@ fn parse_custom_operator() { assert_eq!( select.selection, Some(Expr::BinaryOp { - left: Box::new(Expr::Identifier(Ident { - value: "relname".into(), - quote_style: None, - })), + left: Box::new(Expr::Identifier( + Ident { + value: "relname".into(), + quote_style: None, + } + .empty_span() + )), op: BinaryOperator::PGCustomBinaryOperator(vec!["~".into()]), right: Box::new(Expr::Value(Value::SingleQuotedString("^(table)$".into()))) }) @@ -2419,7 +2449,10 @@ fn parse_delimited_identifiers() { ); match &select.projection[2] { SelectItem::ExprWithAlias { expr, alias } => { - assert_eq!(&Expr::Identifier(Ident::with_quote('"', "simple id")), expr); + assert_eq!( + &Expr::Identifier(Ident::with_quote('"', "simple id").empty_span()), + expr + ); assert_eq!(&Ident::with_quote('"', "column alias"), alias); } _ => panic!("Expected ExprWithAlias"), @@ -2440,7 +2473,7 @@ fn parse_like() { let select = pg().verified_only_select(sql); assert_eq!( Expr::Like { - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier(Ident::new("name").empty_span())), negated, pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))), escape_char: None, @@ -2456,7 +2489,7 @@ fn parse_like() { let select = pg().verified_only_select(sql); assert_eq!( Expr::Like { - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier(Ident::new("name").empty_span())), negated, pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))), escape_char: Some('\\'), @@ -2473,7 +2506,7 @@ fn parse_like() { let select = pg().verified_only_select(sql); assert_eq!( Expr::IsNull(Box::new(Expr::Like { - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier(Ident::new("name").empty_span())), negated, pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))), escape_char: None, @@ -2495,7 +2528,7 @@ fn parse_similar_to() { let select = pg().verified_only_select(sql); assert_eq!( Expr::SimilarTo { - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier(Ident::new("name").empty_span())), negated, pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))), escape_char: None, @@ -2511,7 +2544,7 @@ fn parse_similar_to() { let select = pg().verified_only_select(sql); assert_eq!( Expr::SimilarTo { - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier(Ident::new("name").empty_span())), negated, pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))), escape_char: Some('\\'), @@ -2527,7 +2560,7 @@ fn parse_similar_to() { let select = pg().verified_only_select(sql); assert_eq!( Expr::IsNull(Box::new(Expr::SimilarTo { - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier(Ident::new("name").empty_span())), negated, pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))), escape_char: Some('\\'), @@ -2585,9 +2618,9 @@ fn parse_create_function() { language: Some("SQL".into()), behavior: Some(FunctionBehavior::Immutable), return_: Some(Expr::BinaryOp { - left: Box::new(Expr::Identifier("a".into())), + left: Box::new(Expr::Identifier(Ident::new("a").empty_span())), op: BinaryOperator::Plus, - right: Box::new(Expr::Identifier("b".into())), + right: Box::new(Expr::Identifier(Ident::new("b").empty_span())), }), ..Default::default() }, diff --git a/tests/sqlparser_redshift.rs b/tests/sqlparser_redshift.rs index 7597ee981..c833f4e12 100644 --- a/tests/sqlparser_redshift.rs +++ b/tests/sqlparser_redshift.rs @@ -23,10 +23,13 @@ fn test_square_brackets_over_db_schema_table_name() { let select = redshift().verified_only_select("SELECT [col1] FROM [test_schema].[test_table]"); assert_eq!( select.projection[0], - SelectItem::UnnamedExpr(Expr::Identifier(Ident { - value: "col1".to_string(), - quote_style: Some('[') - })), + SelectItem::UnnamedExpr(Expr::Identifier( + Ident { + value: "col1".to_string(), + quote_style: Some('[') + } + .empty_span() + )), ); assert_eq!( select.from[0], @@ -67,10 +70,13 @@ fn test_double_quotes_over_db_schema_table_name() { redshift().verified_only_select("SELECT \"col1\" FROM \"test_schema\".\"test_table\""); assert_eq!( select.projection[0], - SelectItem::UnnamedExpr(Expr::Identifier(Ident { - value: "col1".to_string(), - quote_style: Some('"') - })), + SelectItem::UnnamedExpr(Expr::Identifier( + Ident { + value: "col1".to_string(), + quote_style: Some('"') + } + .empty_span() + )), ); assert_eq!( select.from[0], @@ -137,7 +143,10 @@ fn parse_delimited_identifiers() { ); match &select.projection[2] { SelectItem::ExprWithAlias { expr, alias } => { - assert_eq!(&Expr::Identifier(Ident::with_quote('"', "simple id")), expr); + assert_eq!( + &Expr::Identifier(Ident::with_quote('"', "simple id").empty_span()), + expr + ); assert_eq!(&Ident::with_quote('"', "column alias"), alias); } _ => panic!("Expected ExprWithAlias"), @@ -158,7 +167,7 @@ fn parse_like() { let select = redshift().verified_only_select(sql); assert_eq!( Expr::Like { - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier(Ident::new("name").empty_span())), negated, pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))), escape_char: None, @@ -174,7 +183,7 @@ fn parse_like() { let select = redshift().verified_only_select(sql); assert_eq!( Expr::Like { - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier(Ident::new("name").empty_span())), negated, pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))), escape_char: Some('\\'), @@ -191,7 +200,7 @@ fn parse_like() { let select = redshift().verified_only_select(sql); assert_eq!( Expr::IsNull(Box::new(Expr::Like { - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier(Ident::new("name").empty_span())), negated, pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))), escape_char: None, @@ -213,7 +222,7 @@ fn parse_similar_to() { let select = redshift().verified_only_select(sql); assert_eq!( Expr::SimilarTo { - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier(Ident::new("name").empty_span())), negated, pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))), escape_char: None, @@ -229,7 +238,7 @@ fn parse_similar_to() { let select = redshift().verified_only_select(sql); assert_eq!( Expr::SimilarTo { - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier(Ident::new("name").empty_span())), negated, pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))), escape_char: Some('\\'), @@ -245,7 +254,7 @@ fn parse_similar_to() { let select = redshift().verified_only_select(sql); assert_eq!( Expr::IsNull(Box::new(Expr::SimilarTo { - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier(Ident::new("name").empty_span())), negated, pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))), escape_char: Some('\\'), @@ -268,7 +277,7 @@ fn test_sharp() { let sql = "SELECT #_of_values"; let select = redshift().verified_only_select(sql); assert_eq!( - SelectItem::UnnamedExpr(Expr::Identifier(Ident::new("#_of_values"))), + SelectItem::UnnamedExpr(Expr::Identifier(Ident::new("#_of_values").empty_span())), select.projection[0] ); } diff --git a/tests/sqlparser_snowflake.rs b/tests/sqlparser_snowflake.rs index 3a02cb627..355066c8f 100644 --- a/tests/sqlparser_snowflake.rs +++ b/tests/sqlparser_snowflake.rs @@ -163,7 +163,7 @@ fn parse_array() { let select = snowflake().verified_only_select(sql); assert_eq!( &Expr::Cast { - expr: Box::new(Expr::Identifier(Ident::new("a"))), + expr: Box::new(Expr::Identifier(Ident::new("a").empty_span())), data_type: DataType::Array(None), }, expr_from_projection(only(&select.projection)) @@ -176,7 +176,7 @@ fn parse_json_using_colon() { let select = snowflake().verified_only_select(sql); assert_eq!( SelectItem::UnnamedExpr(Expr::JsonAccess { - left: Box::new(Expr::Identifier(Ident::new("a"))), + left: Box::new(Expr::Identifier(Ident::new("a").empty_span())), operator: JsonOperator::Colon, right: Box::new(Expr::Value(Value::UnQuotedString("b".to_string()))), }), @@ -187,7 +187,7 @@ fn parse_json_using_colon() { let select = snowflake().verified_only_select(sql); assert_eq!( SelectItem::UnnamedExpr(Expr::JsonAccess { - left: Box::new(Expr::Identifier(Ident::new("a"))), + left: Box::new(Expr::Identifier(Ident::new("a").empty_span())), operator: JsonOperator::Colon, right: Box::new(Expr::Value(Value::UnQuotedString("type".to_string()))), }), @@ -198,7 +198,7 @@ fn parse_json_using_colon() { let select = snowflake().verified_only_select(sql); assert_eq!( SelectItem::UnnamedExpr(Expr::JsonAccess { - left: Box::new(Expr::Identifier(Ident::new("a"))), + left: Box::new(Expr::Identifier(Ident::new("a").empty_span())), operator: JsonOperator::Colon, right: Box::new(Expr::Value(Value::UnQuotedString("location".to_string()))), }), @@ -250,7 +250,10 @@ fn parse_delimited_identifiers() { ); match &select.projection[2] { SelectItem::ExprWithAlias { expr, alias } => { - assert_eq!(&Expr::Identifier(Ident::with_quote('"', "simple id")), expr); + assert_eq!( + &Expr::Identifier(Ident::with_quote('"', "simple id").empty_span()), + expr + ); assert_eq!(&Ident::with_quote('"', "column alias"), alias); } _ => panic!("Expected ExprWithAlias"), @@ -271,7 +274,7 @@ fn parse_like() { let select = snowflake().verified_only_select(sql); assert_eq!( Expr::Like { - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier(Ident::new("name").empty_span())), negated, pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))), escape_char: None, @@ -287,7 +290,7 @@ fn parse_like() { let select = snowflake().verified_only_select(sql); assert_eq!( Expr::Like { - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier(Ident::new("name").empty_span())), negated, pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))), escape_char: Some('\\'), @@ -304,7 +307,7 @@ fn parse_like() { let select = snowflake().verified_only_select(sql); assert_eq!( Expr::IsNull(Box::new(Expr::Like { - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier(Ident::new("name").empty_span())), negated, pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))), escape_char: None, @@ -326,7 +329,7 @@ fn parse_similar_to() { let select = snowflake().verified_only_select(sql); assert_eq!( Expr::SimilarTo { - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier(Ident::new("name").empty_span())), negated, pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))), escape_char: None, @@ -342,7 +345,7 @@ fn parse_similar_to() { let select = snowflake().verified_only_select(sql); assert_eq!( Expr::SimilarTo { - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier(Ident::new("name").empty_span())), negated, pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))), escape_char: Some('\\'), @@ -358,7 +361,7 @@ fn parse_similar_to() { let select = snowflake().verified_only_select(sql); assert_eq!( Expr::IsNull(Box::new(Expr::SimilarTo { - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier(Ident::new("name").empty_span())), negated, pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))), escape_char: Some('\\'), diff --git a/tests/sqlparser_sqlite.rs b/tests/sqlparser_sqlite.rs index 8fc3a8d63..d20ef3f0c 100644 --- a/tests/sqlparser_sqlite.rs +++ b/tests/sqlparser_sqlite.rs @@ -143,7 +143,7 @@ fn parse_like() { let select = sqlite().verified_only_select(sql); assert_eq!( Expr::Like { - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier(Ident::new("name").empty_span())), negated, pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))), escape_char: None, @@ -159,7 +159,7 @@ fn parse_like() { let select = sqlite().verified_only_select(sql); assert_eq!( Expr::Like { - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier(Ident::new("name").empty_span())), negated, pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))), escape_char: Some('\\'), @@ -176,7 +176,7 @@ fn parse_like() { let select = sqlite().verified_only_select(sql); assert_eq!( Expr::IsNull(Box::new(Expr::Like { - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier(Ident::new("name").empty_span())), negated, pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))), escape_char: None, @@ -198,7 +198,7 @@ fn parse_similar_to() { let select = sqlite().verified_only_select(sql); assert_eq!( Expr::SimilarTo { - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier(Ident::new("name").empty_span())), negated, pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))), escape_char: None, @@ -214,7 +214,7 @@ fn parse_similar_to() { let select = sqlite().verified_only_select(sql); assert_eq!( Expr::SimilarTo { - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier(Ident::new("name").empty_span())), negated, pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))), escape_char: Some('\\'), @@ -230,7 +230,7 @@ fn parse_similar_to() { let select = sqlite().verified_only_select(sql); assert_eq!( Expr::IsNull(Box::new(Expr::SimilarTo { - expr: Box::new(Expr::Identifier(Ident::new("name"))), + expr: Box::new(Expr::Identifier(Ident::new("name").empty_span())), negated, pattern: Box::new(Expr::Value(Value::SingleQuotedString("%a".to_string()))), escape_char: Some('\\'),