1#[cfg(not(feature = "std"))]
25use alloc::{
26 borrow::ToOwned,
27 format,
28 string::{String, ToString},
29 vec,
30 vec::Vec,
31};
32use core::num::NonZeroU8;
33use core::str::Chars;
34use core::{cmp, fmt};
35use core::{iter::Peekable, str};
36
37#[cfg(feature = "serde")]
38use serde::{Deserialize, Serialize};
39
40#[cfg(feature = "visitor")]
41use sqlparser_derive::{Visit, VisitMut};
42
43use crate::dialect::Dialect;
44use crate::dialect::{
45 BigQueryDialect, DuckDbDialect, GenericDialect, MySqlDialect, PostgreSqlDialect,
46 SnowflakeDialect,
47};
48use crate::keywords::{Keyword, ALL_KEYWORDS, ALL_KEYWORDS_INDEX};
49use crate::{
50 ast::{DollarQuotedString, QuoteDelimitedString},
51 dialect::HiveDialect,
52};
53
54#[derive(#[automatically_derived]
impl ::core::fmt::Debug for Token {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
Token::EOF => ::core::fmt::Formatter::write_str(f, "EOF"),
Token::Word(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Word",
&__self_0),
Token::Number(__self_0, __self_1) =>
::core::fmt::Formatter::debug_tuple_field2_finish(f, "Number",
__self_0, &__self_1),
Token::Char(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Char",
&__self_0),
Token::SingleQuotedString(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"SingleQuotedString", &__self_0),
Token::DoubleQuotedString(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"DoubleQuotedString", &__self_0),
Token::TripleSingleQuotedString(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"TripleSingleQuotedString", &__self_0),
Token::TripleDoubleQuotedString(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"TripleDoubleQuotedString", &__self_0),
Token::DollarQuotedString(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"DollarQuotedString", &__self_0),
Token::SingleQuotedByteStringLiteral(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"SingleQuotedByteStringLiteral", &__self_0),
Token::DoubleQuotedByteStringLiteral(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"DoubleQuotedByteStringLiteral", &__self_0),
Token::TripleSingleQuotedByteStringLiteral(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"TripleSingleQuotedByteStringLiteral", &__self_0),
Token::TripleDoubleQuotedByteStringLiteral(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"TripleDoubleQuotedByteStringLiteral", &__self_0),
Token::SingleQuotedRawStringLiteral(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"SingleQuotedRawStringLiteral", &__self_0),
Token::DoubleQuotedRawStringLiteral(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"DoubleQuotedRawStringLiteral", &__self_0),
Token::TripleSingleQuotedRawStringLiteral(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"TripleSingleQuotedRawStringLiteral", &__self_0),
Token::TripleDoubleQuotedRawStringLiteral(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"TripleDoubleQuotedRawStringLiteral", &__self_0),
Token::NationalStringLiteral(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"NationalStringLiteral", &__self_0),
Token::QuoteDelimitedStringLiteral(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"QuoteDelimitedStringLiteral", &__self_0),
Token::NationalQuoteDelimitedStringLiteral(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"NationalQuoteDelimitedStringLiteral", &__self_0),
Token::EscapedStringLiteral(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"EscapedStringLiteral", &__self_0),
Token::UnicodeStringLiteral(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"UnicodeStringLiteral", &__self_0),
Token::HexStringLiteral(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"HexStringLiteral", &__self_0),
Token::Comma => ::core::fmt::Formatter::write_str(f, "Comma"),
Token::Whitespace(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"Whitespace", &__self_0),
Token::DoubleEq =>
::core::fmt::Formatter::write_str(f, "DoubleEq"),
Token::Eq => ::core::fmt::Formatter::write_str(f, "Eq"),
Token::Neq => ::core::fmt::Formatter::write_str(f, "Neq"),
Token::Lt => ::core::fmt::Formatter::write_str(f, "Lt"),
Token::Gt => ::core::fmt::Formatter::write_str(f, "Gt"),
Token::LtEq => ::core::fmt::Formatter::write_str(f, "LtEq"),
Token::GtEq => ::core::fmt::Formatter::write_str(f, "GtEq"),
Token::Spaceship =>
::core::fmt::Formatter::write_str(f, "Spaceship"),
Token::Plus => ::core::fmt::Formatter::write_str(f, "Plus"),
Token::Minus => ::core::fmt::Formatter::write_str(f, "Minus"),
Token::Mul => ::core::fmt::Formatter::write_str(f, "Mul"),
Token::Div => ::core::fmt::Formatter::write_str(f, "Div"),
Token::DuckIntDiv =>
::core::fmt::Formatter::write_str(f, "DuckIntDiv"),
Token::Mod => ::core::fmt::Formatter::write_str(f, "Mod"),
Token::StringConcat =>
::core::fmt::Formatter::write_str(f, "StringConcat"),
Token::LParen => ::core::fmt::Formatter::write_str(f, "LParen"),
Token::RParen => ::core::fmt::Formatter::write_str(f, "RParen"),
Token::Period => ::core::fmt::Formatter::write_str(f, "Period"),
Token::Colon => ::core::fmt::Formatter::write_str(f, "Colon"),
Token::DoubleColon =>
::core::fmt::Formatter::write_str(f, "DoubleColon"),
Token::Assignment =>
::core::fmt::Formatter::write_str(f, "Assignment"),
Token::SemiColon =>
::core::fmt::Formatter::write_str(f, "SemiColon"),
Token::Backslash =>
::core::fmt::Formatter::write_str(f, "Backslash"),
Token::LBracket =>
::core::fmt::Formatter::write_str(f, "LBracket"),
Token::RBracket =>
::core::fmt::Formatter::write_str(f, "RBracket"),
Token::Ampersand =>
::core::fmt::Formatter::write_str(f, "Ampersand"),
Token::Pipe => ::core::fmt::Formatter::write_str(f, "Pipe"),
Token::Caret => ::core::fmt::Formatter::write_str(f, "Caret"),
Token::LBrace => ::core::fmt::Formatter::write_str(f, "LBrace"),
Token::RBrace => ::core::fmt::Formatter::write_str(f, "RBrace"),
Token::RArrow => ::core::fmt::Formatter::write_str(f, "RArrow"),
Token::Sharp => ::core::fmt::Formatter::write_str(f, "Sharp"),
Token::DoubleSharp =>
::core::fmt::Formatter::write_str(f, "DoubleSharp"),
Token::Tilde => ::core::fmt::Formatter::write_str(f, "Tilde"),
Token::TildeAsterisk =>
::core::fmt::Formatter::write_str(f, "TildeAsterisk"),
Token::ExclamationMarkTilde =>
::core::fmt::Formatter::write_str(f, "ExclamationMarkTilde"),
Token::ExclamationMarkTildeAsterisk =>
::core::fmt::Formatter::write_str(f,
"ExclamationMarkTildeAsterisk"),
Token::DoubleTilde =>
::core::fmt::Formatter::write_str(f, "DoubleTilde"),
Token::DoubleTildeAsterisk =>
::core::fmt::Formatter::write_str(f, "DoubleTildeAsterisk"),
Token::ExclamationMarkDoubleTilde =>
::core::fmt::Formatter::write_str(f,
"ExclamationMarkDoubleTilde"),
Token::ExclamationMarkDoubleTildeAsterisk =>
::core::fmt::Formatter::write_str(f,
"ExclamationMarkDoubleTildeAsterisk"),
Token::ShiftLeft =>
::core::fmt::Formatter::write_str(f, "ShiftLeft"),
Token::ShiftRight =>
::core::fmt::Formatter::write_str(f, "ShiftRight"),
Token::Overlap => ::core::fmt::Formatter::write_str(f, "Overlap"),
Token::ExclamationMark =>
::core::fmt::Formatter::write_str(f, "ExclamationMark"),
Token::DoubleExclamationMark =>
::core::fmt::Formatter::write_str(f, "DoubleExclamationMark"),
Token::AtSign => ::core::fmt::Formatter::write_str(f, "AtSign"),
Token::CaretAt => ::core::fmt::Formatter::write_str(f, "CaretAt"),
Token::PGSquareRoot =>
::core::fmt::Formatter::write_str(f, "PGSquareRoot"),
Token::PGCubeRoot =>
::core::fmt::Formatter::write_str(f, "PGCubeRoot"),
Token::Placeholder(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"Placeholder", &__self_0),
Token::Arrow => ::core::fmt::Formatter::write_str(f, "Arrow"),
Token::LongArrow =>
::core::fmt::Formatter::write_str(f, "LongArrow"),
Token::HashArrow =>
::core::fmt::Formatter::write_str(f, "HashArrow"),
Token::AtDashAt =>
::core::fmt::Formatter::write_str(f, "AtDashAt"),
Token::QuestionMarkDash =>
::core::fmt::Formatter::write_str(f, "QuestionMarkDash"),
Token::AmpersandLeftAngleBracket =>
::core::fmt::Formatter::write_str(f,
"AmpersandLeftAngleBracket"),
Token::AmpersandRightAngleBracket =>
::core::fmt::Formatter::write_str(f,
"AmpersandRightAngleBracket"),
Token::AmpersandLeftAngleBracketVerticalBar =>
::core::fmt::Formatter::write_str(f,
"AmpersandLeftAngleBracketVerticalBar"),
Token::VerticalBarAmpersandRightAngleBracket =>
::core::fmt::Formatter::write_str(f,
"VerticalBarAmpersandRightAngleBracket"),
Token::TwoWayArrow =>
::core::fmt::Formatter::write_str(f, "TwoWayArrow"),
Token::LeftAngleBracketCaret =>
::core::fmt::Formatter::write_str(f, "LeftAngleBracketCaret"),
Token::RightAngleBracketCaret =>
::core::fmt::Formatter::write_str(f,
"RightAngleBracketCaret"),
Token::QuestionMarkSharp =>
::core::fmt::Formatter::write_str(f, "QuestionMarkSharp"),
Token::QuestionMarkDashVerticalBar =>
::core::fmt::Formatter::write_str(f,
"QuestionMarkDashVerticalBar"),
Token::QuestionMarkDoubleVerticalBar =>
::core::fmt::Formatter::write_str(f,
"QuestionMarkDoubleVerticalBar"),
Token::TildeEqual =>
::core::fmt::Formatter::write_str(f, "TildeEqual"),
Token::ShiftLeftVerticalBar =>
::core::fmt::Formatter::write_str(f, "ShiftLeftVerticalBar"),
Token::VerticalBarShiftRight =>
::core::fmt::Formatter::write_str(f, "VerticalBarShiftRight"),
Token::VerticalBarRightAngleBracket =>
::core::fmt::Formatter::write_str(f,
"VerticalBarRightAngleBracket"),
Token::HashLongArrow =>
::core::fmt::Formatter::write_str(f, "HashLongArrow"),
Token::AtArrow => ::core::fmt::Formatter::write_str(f, "AtArrow"),
Token::ArrowAt => ::core::fmt::Formatter::write_str(f, "ArrowAt"),
Token::HashMinus =>
::core::fmt::Formatter::write_str(f, "HashMinus"),
Token::AtQuestion =>
::core::fmt::Formatter::write_str(f, "AtQuestion"),
Token::AtAt => ::core::fmt::Formatter::write_str(f, "AtAt"),
Token::Question =>
::core::fmt::Formatter::write_str(f, "Question"),
Token::QuestionAnd =>
::core::fmt::Formatter::write_str(f, "QuestionAnd"),
Token::QuestionPipe =>
::core::fmt::Formatter::write_str(f, "QuestionPipe"),
Token::CustomBinaryOperator(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"CustomBinaryOperator", &__self_0),
}
}
}Debug, #[automatically_derived]
impl ::core::clone::Clone for Token {
#[inline]
fn clone(&self) -> Token {
match self {
Token::EOF => Token::EOF,
Token::Word(__self_0) =>
Token::Word(::core::clone::Clone::clone(__self_0)),
Token::Number(__self_0, __self_1) =>
Token::Number(::core::clone::Clone::clone(__self_0),
::core::clone::Clone::clone(__self_1)),
Token::Char(__self_0) =>
Token::Char(::core::clone::Clone::clone(__self_0)),
Token::SingleQuotedString(__self_0) =>
Token::SingleQuotedString(::core::clone::Clone::clone(__self_0)),
Token::DoubleQuotedString(__self_0) =>
Token::DoubleQuotedString(::core::clone::Clone::clone(__self_0)),
Token::TripleSingleQuotedString(__self_0) =>
Token::TripleSingleQuotedString(::core::clone::Clone::clone(__self_0)),
Token::TripleDoubleQuotedString(__self_0) =>
Token::TripleDoubleQuotedString(::core::clone::Clone::clone(__self_0)),
Token::DollarQuotedString(__self_0) =>
Token::DollarQuotedString(::core::clone::Clone::clone(__self_0)),
Token::SingleQuotedByteStringLiteral(__self_0) =>
Token::SingleQuotedByteStringLiteral(::core::clone::Clone::clone(__self_0)),
Token::DoubleQuotedByteStringLiteral(__self_0) =>
Token::DoubleQuotedByteStringLiteral(::core::clone::Clone::clone(__self_0)),
Token::TripleSingleQuotedByteStringLiteral(__self_0) =>
Token::TripleSingleQuotedByteStringLiteral(::core::clone::Clone::clone(__self_0)),
Token::TripleDoubleQuotedByteStringLiteral(__self_0) =>
Token::TripleDoubleQuotedByteStringLiteral(::core::clone::Clone::clone(__self_0)),
Token::SingleQuotedRawStringLiteral(__self_0) =>
Token::SingleQuotedRawStringLiteral(::core::clone::Clone::clone(__self_0)),
Token::DoubleQuotedRawStringLiteral(__self_0) =>
Token::DoubleQuotedRawStringLiteral(::core::clone::Clone::clone(__self_0)),
Token::TripleSingleQuotedRawStringLiteral(__self_0) =>
Token::TripleSingleQuotedRawStringLiteral(::core::clone::Clone::clone(__self_0)),
Token::TripleDoubleQuotedRawStringLiteral(__self_0) =>
Token::TripleDoubleQuotedRawStringLiteral(::core::clone::Clone::clone(__self_0)),
Token::NationalStringLiteral(__self_0) =>
Token::NationalStringLiteral(::core::clone::Clone::clone(__self_0)),
Token::QuoteDelimitedStringLiteral(__self_0) =>
Token::QuoteDelimitedStringLiteral(::core::clone::Clone::clone(__self_0)),
Token::NationalQuoteDelimitedStringLiteral(__self_0) =>
Token::NationalQuoteDelimitedStringLiteral(::core::clone::Clone::clone(__self_0)),
Token::EscapedStringLiteral(__self_0) =>
Token::EscapedStringLiteral(::core::clone::Clone::clone(__self_0)),
Token::UnicodeStringLiteral(__self_0) =>
Token::UnicodeStringLiteral(::core::clone::Clone::clone(__self_0)),
Token::HexStringLiteral(__self_0) =>
Token::HexStringLiteral(::core::clone::Clone::clone(__self_0)),
Token::Comma => Token::Comma,
Token::Whitespace(__self_0) =>
Token::Whitespace(::core::clone::Clone::clone(__self_0)),
Token::DoubleEq => Token::DoubleEq,
Token::Eq => Token::Eq,
Token::Neq => Token::Neq,
Token::Lt => Token::Lt,
Token::Gt => Token::Gt,
Token::LtEq => Token::LtEq,
Token::GtEq => Token::GtEq,
Token::Spaceship => Token::Spaceship,
Token::Plus => Token::Plus,
Token::Minus => Token::Minus,
Token::Mul => Token::Mul,
Token::Div => Token::Div,
Token::DuckIntDiv => Token::DuckIntDiv,
Token::Mod => Token::Mod,
Token::StringConcat => Token::StringConcat,
Token::LParen => Token::LParen,
Token::RParen => Token::RParen,
Token::Period => Token::Period,
Token::Colon => Token::Colon,
Token::DoubleColon => Token::DoubleColon,
Token::Assignment => Token::Assignment,
Token::SemiColon => Token::SemiColon,
Token::Backslash => Token::Backslash,
Token::LBracket => Token::LBracket,
Token::RBracket => Token::RBracket,
Token::Ampersand => Token::Ampersand,
Token::Pipe => Token::Pipe,
Token::Caret => Token::Caret,
Token::LBrace => Token::LBrace,
Token::RBrace => Token::RBrace,
Token::RArrow => Token::RArrow,
Token::Sharp => Token::Sharp,
Token::DoubleSharp => Token::DoubleSharp,
Token::Tilde => Token::Tilde,
Token::TildeAsterisk => Token::TildeAsterisk,
Token::ExclamationMarkTilde => Token::ExclamationMarkTilde,
Token::ExclamationMarkTildeAsterisk =>
Token::ExclamationMarkTildeAsterisk,
Token::DoubleTilde => Token::DoubleTilde,
Token::DoubleTildeAsterisk => Token::DoubleTildeAsterisk,
Token::ExclamationMarkDoubleTilde =>
Token::ExclamationMarkDoubleTilde,
Token::ExclamationMarkDoubleTildeAsterisk =>
Token::ExclamationMarkDoubleTildeAsterisk,
Token::ShiftLeft => Token::ShiftLeft,
Token::ShiftRight => Token::ShiftRight,
Token::Overlap => Token::Overlap,
Token::ExclamationMark => Token::ExclamationMark,
Token::DoubleExclamationMark => Token::DoubleExclamationMark,
Token::AtSign => Token::AtSign,
Token::CaretAt => Token::CaretAt,
Token::PGSquareRoot => Token::PGSquareRoot,
Token::PGCubeRoot => Token::PGCubeRoot,
Token::Placeholder(__self_0) =>
Token::Placeholder(::core::clone::Clone::clone(__self_0)),
Token::Arrow => Token::Arrow,
Token::LongArrow => Token::LongArrow,
Token::HashArrow => Token::HashArrow,
Token::AtDashAt => Token::AtDashAt,
Token::QuestionMarkDash => Token::QuestionMarkDash,
Token::AmpersandLeftAngleBracket =>
Token::AmpersandLeftAngleBracket,
Token::AmpersandRightAngleBracket =>
Token::AmpersandRightAngleBracket,
Token::AmpersandLeftAngleBracketVerticalBar =>
Token::AmpersandLeftAngleBracketVerticalBar,
Token::VerticalBarAmpersandRightAngleBracket =>
Token::VerticalBarAmpersandRightAngleBracket,
Token::TwoWayArrow => Token::TwoWayArrow,
Token::LeftAngleBracketCaret => Token::LeftAngleBracketCaret,
Token::RightAngleBracketCaret => Token::RightAngleBracketCaret,
Token::QuestionMarkSharp => Token::QuestionMarkSharp,
Token::QuestionMarkDashVerticalBar =>
Token::QuestionMarkDashVerticalBar,
Token::QuestionMarkDoubleVerticalBar =>
Token::QuestionMarkDoubleVerticalBar,
Token::TildeEqual => Token::TildeEqual,
Token::ShiftLeftVerticalBar => Token::ShiftLeftVerticalBar,
Token::VerticalBarShiftRight => Token::VerticalBarShiftRight,
Token::VerticalBarRightAngleBracket =>
Token::VerticalBarRightAngleBracket,
Token::HashLongArrow => Token::HashLongArrow,
Token::AtArrow => Token::AtArrow,
Token::ArrowAt => Token::ArrowAt,
Token::HashMinus => Token::HashMinus,
Token::AtQuestion => Token::AtQuestion,
Token::AtAt => Token::AtAt,
Token::Question => Token::Question,
Token::QuestionAnd => Token::QuestionAnd,
Token::QuestionPipe => Token::QuestionPipe,
Token::CustomBinaryOperator(__self_0) =>
Token::CustomBinaryOperator(::core::clone::Clone::clone(__self_0)),
}
}
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for Token {
#[inline]
fn eq(&self, other: &Token) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr &&
match (self, other) {
(Token::Word(__self_0), Token::Word(__arg1_0)) =>
__self_0 == __arg1_0,
(Token::Number(__self_0, __self_1),
Token::Number(__arg1_0, __arg1_1)) =>
__self_1 == __arg1_1 && __self_0 == __arg1_0,
(Token::Char(__self_0), Token::Char(__arg1_0)) =>
__self_0 == __arg1_0,
(Token::SingleQuotedString(__self_0),
Token::SingleQuotedString(__arg1_0)) =>
__self_0 == __arg1_0,
(Token::DoubleQuotedString(__self_0),
Token::DoubleQuotedString(__arg1_0)) =>
__self_0 == __arg1_0,
(Token::TripleSingleQuotedString(__self_0),
Token::TripleSingleQuotedString(__arg1_0)) =>
__self_0 == __arg1_0,
(Token::TripleDoubleQuotedString(__self_0),
Token::TripleDoubleQuotedString(__arg1_0)) =>
__self_0 == __arg1_0,
(Token::DollarQuotedString(__self_0),
Token::DollarQuotedString(__arg1_0)) =>
__self_0 == __arg1_0,
(Token::SingleQuotedByteStringLiteral(__self_0),
Token::SingleQuotedByteStringLiteral(__arg1_0)) =>
__self_0 == __arg1_0,
(Token::DoubleQuotedByteStringLiteral(__self_0),
Token::DoubleQuotedByteStringLiteral(__arg1_0)) =>
__self_0 == __arg1_0,
(Token::TripleSingleQuotedByteStringLiteral(__self_0),
Token::TripleSingleQuotedByteStringLiteral(__arg1_0)) =>
__self_0 == __arg1_0,
(Token::TripleDoubleQuotedByteStringLiteral(__self_0),
Token::TripleDoubleQuotedByteStringLiteral(__arg1_0)) =>
__self_0 == __arg1_0,
(Token::SingleQuotedRawStringLiteral(__self_0),
Token::SingleQuotedRawStringLiteral(__arg1_0)) =>
__self_0 == __arg1_0,
(Token::DoubleQuotedRawStringLiteral(__self_0),
Token::DoubleQuotedRawStringLiteral(__arg1_0)) =>
__self_0 == __arg1_0,
(Token::TripleSingleQuotedRawStringLiteral(__self_0),
Token::TripleSingleQuotedRawStringLiteral(__arg1_0)) =>
__self_0 == __arg1_0,
(Token::TripleDoubleQuotedRawStringLiteral(__self_0),
Token::TripleDoubleQuotedRawStringLiteral(__arg1_0)) =>
__self_0 == __arg1_0,
(Token::NationalStringLiteral(__self_0),
Token::NationalStringLiteral(__arg1_0)) =>
__self_0 == __arg1_0,
(Token::QuoteDelimitedStringLiteral(__self_0),
Token::QuoteDelimitedStringLiteral(__arg1_0)) =>
__self_0 == __arg1_0,
(Token::NationalQuoteDelimitedStringLiteral(__self_0),
Token::NationalQuoteDelimitedStringLiteral(__arg1_0)) =>
__self_0 == __arg1_0,
(Token::EscapedStringLiteral(__self_0),
Token::EscapedStringLiteral(__arg1_0)) =>
__self_0 == __arg1_0,
(Token::UnicodeStringLiteral(__self_0),
Token::UnicodeStringLiteral(__arg1_0)) =>
__self_0 == __arg1_0,
(Token::HexStringLiteral(__self_0),
Token::HexStringLiteral(__arg1_0)) => __self_0 == __arg1_0,
(Token::Whitespace(__self_0), Token::Whitespace(__arg1_0)) =>
__self_0 == __arg1_0,
(Token::Placeholder(__self_0), Token::Placeholder(__arg1_0))
=> __self_0 == __arg1_0,
(Token::CustomBinaryOperator(__self_0),
Token::CustomBinaryOperator(__arg1_0)) =>
__self_0 == __arg1_0,
_ => true,
}
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::PartialOrd for Token {
#[inline]
fn partial_cmp(&self, other: &Token)
-> ::core::option::Option<::core::cmp::Ordering> {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
match ::core::cmp::PartialOrd::partial_cmp(&__self_discr,
&__arg1_discr) {
::core::option::Option::Some(::core::cmp::Ordering::Equal) =>
match (self, other) {
(Token::Word(__self_0), Token::Word(__arg1_0)) =>
::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
(Token::Number(__self_0, __self_1),
Token::Number(__arg1_0, __arg1_1)) =>
match ::core::cmp::PartialOrd::partial_cmp(__self_0,
__arg1_0) {
::core::option::Option::Some(::core::cmp::Ordering::Equal)
=> ::core::cmp::PartialOrd::partial_cmp(__self_1, __arg1_1),
cmp => cmp,
},
(Token::Char(__self_0), Token::Char(__arg1_0)) =>
::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
(Token::SingleQuotedString(__self_0),
Token::SingleQuotedString(__arg1_0)) =>
::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
(Token::DoubleQuotedString(__self_0),
Token::DoubleQuotedString(__arg1_0)) =>
::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
(Token::TripleSingleQuotedString(__self_0),
Token::TripleSingleQuotedString(__arg1_0)) =>
::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
(Token::TripleDoubleQuotedString(__self_0),
Token::TripleDoubleQuotedString(__arg1_0)) =>
::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
(Token::DollarQuotedString(__self_0),
Token::DollarQuotedString(__arg1_0)) =>
::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
(Token::SingleQuotedByteStringLiteral(__self_0),
Token::SingleQuotedByteStringLiteral(__arg1_0)) =>
::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
(Token::DoubleQuotedByteStringLiteral(__self_0),
Token::DoubleQuotedByteStringLiteral(__arg1_0)) =>
::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
(Token::TripleSingleQuotedByteStringLiteral(__self_0),
Token::TripleSingleQuotedByteStringLiteral(__arg1_0)) =>
::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
(Token::TripleDoubleQuotedByteStringLiteral(__self_0),
Token::TripleDoubleQuotedByteStringLiteral(__arg1_0)) =>
::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
(Token::SingleQuotedRawStringLiteral(__self_0),
Token::SingleQuotedRawStringLiteral(__arg1_0)) =>
::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
(Token::DoubleQuotedRawStringLiteral(__self_0),
Token::DoubleQuotedRawStringLiteral(__arg1_0)) =>
::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
(Token::TripleSingleQuotedRawStringLiteral(__self_0),
Token::TripleSingleQuotedRawStringLiteral(__arg1_0)) =>
::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
(Token::TripleDoubleQuotedRawStringLiteral(__self_0),
Token::TripleDoubleQuotedRawStringLiteral(__arg1_0)) =>
::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
(Token::NationalStringLiteral(__self_0),
Token::NationalStringLiteral(__arg1_0)) =>
::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
(Token::QuoteDelimitedStringLiteral(__self_0),
Token::QuoteDelimitedStringLiteral(__arg1_0)) =>
::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
(Token::NationalQuoteDelimitedStringLiteral(__self_0),
Token::NationalQuoteDelimitedStringLiteral(__arg1_0)) =>
::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
(Token::EscapedStringLiteral(__self_0),
Token::EscapedStringLiteral(__arg1_0)) =>
::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
(Token::UnicodeStringLiteral(__self_0),
Token::UnicodeStringLiteral(__arg1_0)) =>
::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
(Token::HexStringLiteral(__self_0),
Token::HexStringLiteral(__arg1_0)) =>
::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
(Token::Whitespace(__self_0), Token::Whitespace(__arg1_0))
=> ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
(Token::Placeholder(__self_0), Token::Placeholder(__arg1_0))
=> ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
(Token::CustomBinaryOperator(__self_0),
Token::CustomBinaryOperator(__arg1_0)) =>
::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
_ =>
::core::option::Option::Some(::core::cmp::Ordering::Equal),
},
cmp => cmp,
}
}
}PartialOrd, #[automatically_derived]
impl ::core::cmp::Eq for Token {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<Word>;
let _: ::core::cmp::AssertParamIsEq<String>;
let _: ::core::cmp::AssertParamIsEq<bool>;
let _: ::core::cmp::AssertParamIsEq<char>;
let _: ::core::cmp::AssertParamIsEq<DollarQuotedString>;
let _: ::core::cmp::AssertParamIsEq<QuoteDelimitedString>;
let _: ::core::cmp::AssertParamIsEq<Whitespace>;
}
}Eq, #[automatically_derived]
impl ::core::cmp::Ord for Token {
#[inline]
fn cmp(&self, other: &Token) -> ::core::cmp::Ordering {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
match ::core::cmp::Ord::cmp(&__self_discr, &__arg1_discr) {
::core::cmp::Ordering::Equal =>
match (self, other) {
(Token::Word(__self_0), Token::Word(__arg1_0)) =>
::core::cmp::Ord::cmp(__self_0, __arg1_0),
(Token::Number(__self_0, __self_1),
Token::Number(__arg1_0, __arg1_1)) =>
match ::core::cmp::Ord::cmp(__self_0, __arg1_0) {
::core::cmp::Ordering::Equal =>
::core::cmp::Ord::cmp(__self_1, __arg1_1),
cmp => cmp,
},
(Token::Char(__self_0), Token::Char(__arg1_0)) =>
::core::cmp::Ord::cmp(__self_0, __arg1_0),
(Token::SingleQuotedString(__self_0),
Token::SingleQuotedString(__arg1_0)) =>
::core::cmp::Ord::cmp(__self_0, __arg1_0),
(Token::DoubleQuotedString(__self_0),
Token::DoubleQuotedString(__arg1_0)) =>
::core::cmp::Ord::cmp(__self_0, __arg1_0),
(Token::TripleSingleQuotedString(__self_0),
Token::TripleSingleQuotedString(__arg1_0)) =>
::core::cmp::Ord::cmp(__self_0, __arg1_0),
(Token::TripleDoubleQuotedString(__self_0),
Token::TripleDoubleQuotedString(__arg1_0)) =>
::core::cmp::Ord::cmp(__self_0, __arg1_0),
(Token::DollarQuotedString(__self_0),
Token::DollarQuotedString(__arg1_0)) =>
::core::cmp::Ord::cmp(__self_0, __arg1_0),
(Token::SingleQuotedByteStringLiteral(__self_0),
Token::SingleQuotedByteStringLiteral(__arg1_0)) =>
::core::cmp::Ord::cmp(__self_0, __arg1_0),
(Token::DoubleQuotedByteStringLiteral(__self_0),
Token::DoubleQuotedByteStringLiteral(__arg1_0)) =>
::core::cmp::Ord::cmp(__self_0, __arg1_0),
(Token::TripleSingleQuotedByteStringLiteral(__self_0),
Token::TripleSingleQuotedByteStringLiteral(__arg1_0)) =>
::core::cmp::Ord::cmp(__self_0, __arg1_0),
(Token::TripleDoubleQuotedByteStringLiteral(__self_0),
Token::TripleDoubleQuotedByteStringLiteral(__arg1_0)) =>
::core::cmp::Ord::cmp(__self_0, __arg1_0),
(Token::SingleQuotedRawStringLiteral(__self_0),
Token::SingleQuotedRawStringLiteral(__arg1_0)) =>
::core::cmp::Ord::cmp(__self_0, __arg1_0),
(Token::DoubleQuotedRawStringLiteral(__self_0),
Token::DoubleQuotedRawStringLiteral(__arg1_0)) =>
::core::cmp::Ord::cmp(__self_0, __arg1_0),
(Token::TripleSingleQuotedRawStringLiteral(__self_0),
Token::TripleSingleQuotedRawStringLiteral(__arg1_0)) =>
::core::cmp::Ord::cmp(__self_0, __arg1_0),
(Token::TripleDoubleQuotedRawStringLiteral(__self_0),
Token::TripleDoubleQuotedRawStringLiteral(__arg1_0)) =>
::core::cmp::Ord::cmp(__self_0, __arg1_0),
(Token::NationalStringLiteral(__self_0),
Token::NationalStringLiteral(__arg1_0)) =>
::core::cmp::Ord::cmp(__self_0, __arg1_0),
(Token::QuoteDelimitedStringLiteral(__self_0),
Token::QuoteDelimitedStringLiteral(__arg1_0)) =>
::core::cmp::Ord::cmp(__self_0, __arg1_0),
(Token::NationalQuoteDelimitedStringLiteral(__self_0),
Token::NationalQuoteDelimitedStringLiteral(__arg1_0)) =>
::core::cmp::Ord::cmp(__self_0, __arg1_0),
(Token::EscapedStringLiteral(__self_0),
Token::EscapedStringLiteral(__arg1_0)) =>
::core::cmp::Ord::cmp(__self_0, __arg1_0),
(Token::UnicodeStringLiteral(__self_0),
Token::UnicodeStringLiteral(__arg1_0)) =>
::core::cmp::Ord::cmp(__self_0, __arg1_0),
(Token::HexStringLiteral(__self_0),
Token::HexStringLiteral(__arg1_0)) =>
::core::cmp::Ord::cmp(__self_0, __arg1_0),
(Token::Whitespace(__self_0), Token::Whitespace(__arg1_0))
=> ::core::cmp::Ord::cmp(__self_0, __arg1_0),
(Token::Placeholder(__self_0), Token::Placeholder(__arg1_0))
=> ::core::cmp::Ord::cmp(__self_0, __arg1_0),
(Token::CustomBinaryOperator(__self_0),
Token::CustomBinaryOperator(__arg1_0)) =>
::core::cmp::Ord::cmp(__self_0, __arg1_0),
_ => ::core::cmp::Ordering::Equal,
},
cmp => cmp,
}
}
}Ord, #[automatically_derived]
impl ::core::hash::Hash for Token {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
let __self_discr = ::core::intrinsics::discriminant_value(self);
::core::hash::Hash::hash(&__self_discr, state);
match self {
Token::Word(__self_0) =>
::core::hash::Hash::hash(__self_0, state),
Token::Number(__self_0, __self_1) => {
::core::hash::Hash::hash(__self_0, state);
::core::hash::Hash::hash(__self_1, state)
}
Token::Char(__self_0) =>
::core::hash::Hash::hash(__self_0, state),
Token::SingleQuotedString(__self_0) =>
::core::hash::Hash::hash(__self_0, state),
Token::DoubleQuotedString(__self_0) =>
::core::hash::Hash::hash(__self_0, state),
Token::TripleSingleQuotedString(__self_0) =>
::core::hash::Hash::hash(__self_0, state),
Token::TripleDoubleQuotedString(__self_0) =>
::core::hash::Hash::hash(__self_0, state),
Token::DollarQuotedString(__self_0) =>
::core::hash::Hash::hash(__self_0, state),
Token::SingleQuotedByteStringLiteral(__self_0) =>
::core::hash::Hash::hash(__self_0, state),
Token::DoubleQuotedByteStringLiteral(__self_0) =>
::core::hash::Hash::hash(__self_0, state),
Token::TripleSingleQuotedByteStringLiteral(__self_0) =>
::core::hash::Hash::hash(__self_0, state),
Token::TripleDoubleQuotedByteStringLiteral(__self_0) =>
::core::hash::Hash::hash(__self_0, state),
Token::SingleQuotedRawStringLiteral(__self_0) =>
::core::hash::Hash::hash(__self_0, state),
Token::DoubleQuotedRawStringLiteral(__self_0) =>
::core::hash::Hash::hash(__self_0, state),
Token::TripleSingleQuotedRawStringLiteral(__self_0) =>
::core::hash::Hash::hash(__self_0, state),
Token::TripleDoubleQuotedRawStringLiteral(__self_0) =>
::core::hash::Hash::hash(__self_0, state),
Token::NationalStringLiteral(__self_0) =>
::core::hash::Hash::hash(__self_0, state),
Token::QuoteDelimitedStringLiteral(__self_0) =>
::core::hash::Hash::hash(__self_0, state),
Token::NationalQuoteDelimitedStringLiteral(__self_0) =>
::core::hash::Hash::hash(__self_0, state),
Token::EscapedStringLiteral(__self_0) =>
::core::hash::Hash::hash(__self_0, state),
Token::UnicodeStringLiteral(__self_0) =>
::core::hash::Hash::hash(__self_0, state),
Token::HexStringLiteral(__self_0) =>
::core::hash::Hash::hash(__self_0, state),
Token::Whitespace(__self_0) =>
::core::hash::Hash::hash(__self_0, state),
Token::Placeholder(__self_0) =>
::core::hash::Hash::hash(__self_0, state),
Token::CustomBinaryOperator(__self_0) =>
::core::hash::Hash::hash(__self_0, state),
_ => {}
}
}
}Hash)]
56#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
57#[cfg_attr(feature = "visitor", derive(impl sqlparser::ast::Visit for Token {
fn visit<V: sqlparser::ast::Visitor>(&self, visitor: &mut V)
-> ::std::ops::ControlFlow<V::Break> {
::recursive::__impl::stacker::maybe_grow(::recursive::get_minimum_stack_size(),
::recursive::get_stack_allocation_size(),
move || -> ::std::ops::ControlFlow<V::Break>
{
{
match self {
Self::EOF => {}
Self::Word(_0) => {
sqlparser::ast::Visit::visit(_0, visitor)?;
}
Self::Number(_0, _1) => {
sqlparser::ast::Visit::visit(_0, visitor)?;
sqlparser::ast::Visit::visit(_1, visitor)?;
}
Self::Char(_0) => {
sqlparser::ast::Visit::visit(_0, visitor)?;
}
Self::SingleQuotedString(_0) => {
sqlparser::ast::Visit::visit(_0, visitor)?;
}
Self::DoubleQuotedString(_0) => {
sqlparser::ast::Visit::visit(_0, visitor)?;
}
Self::TripleSingleQuotedString(_0) => {
sqlparser::ast::Visit::visit(_0, visitor)?;
}
Self::TripleDoubleQuotedString(_0) => {
sqlparser::ast::Visit::visit(_0, visitor)?;
}
Self::DollarQuotedString(_0) => {
sqlparser::ast::Visit::visit(_0, visitor)?;
}
Self::SingleQuotedByteStringLiteral(_0) => {
sqlparser::ast::Visit::visit(_0, visitor)?;
}
Self::DoubleQuotedByteStringLiteral(_0) => {
sqlparser::ast::Visit::visit(_0, visitor)?;
}
Self::TripleSingleQuotedByteStringLiteral(_0) => {
sqlparser::ast::Visit::visit(_0, visitor)?;
}
Self::TripleDoubleQuotedByteStringLiteral(_0) => {
sqlparser::ast::Visit::visit(_0, visitor)?;
}
Self::SingleQuotedRawStringLiteral(_0) => {
sqlparser::ast::Visit::visit(_0, visitor)?;
}
Self::DoubleQuotedRawStringLiteral(_0) => {
sqlparser::ast::Visit::visit(_0, visitor)?;
}
Self::TripleSingleQuotedRawStringLiteral(_0) => {
sqlparser::ast::Visit::visit(_0, visitor)?;
}
Self::TripleDoubleQuotedRawStringLiteral(_0) => {
sqlparser::ast::Visit::visit(_0, visitor)?;
}
Self::NationalStringLiteral(_0) => {
sqlparser::ast::Visit::visit(_0, visitor)?;
}
Self::QuoteDelimitedStringLiteral(_0) => {
sqlparser::ast::Visit::visit(_0, visitor)?;
}
Self::NationalQuoteDelimitedStringLiteral(_0) => {
sqlparser::ast::Visit::visit(_0, visitor)?;
}
Self::EscapedStringLiteral(_0) => {
sqlparser::ast::Visit::visit(_0, visitor)?;
}
Self::UnicodeStringLiteral(_0) => {
sqlparser::ast::Visit::visit(_0, visitor)?;
}
Self::HexStringLiteral(_0) => {
sqlparser::ast::Visit::visit(_0, visitor)?;
}
Self::Comma => {}
Self::Whitespace(_0) => {
sqlparser::ast::Visit::visit(_0, visitor)?;
}
Self::DoubleEq => {}
Self::Eq => {}
Self::Neq => {}
Self::Lt => {}
Self::Gt => {}
Self::LtEq => {}
Self::GtEq => {}
Self::Spaceship => {}
Self::Plus => {}
Self::Minus => {}
Self::Mul => {}
Self::Div => {}
Self::DuckIntDiv => {}
Self::Mod => {}
Self::StringConcat => {}
Self::LParen => {}
Self::RParen => {}
Self::Period => {}
Self::Colon => {}
Self::DoubleColon => {}
Self::Assignment => {}
Self::SemiColon => {}
Self::Backslash => {}
Self::LBracket => {}
Self::RBracket => {}
Self::Ampersand => {}
Self::Pipe => {}
Self::Caret => {}
Self::LBrace => {}
Self::RBrace => {}
Self::RArrow => {}
Self::Sharp => {}
Self::DoubleSharp => {}
Self::Tilde => {}
Self::TildeAsterisk => {}
Self::ExclamationMarkTilde => {}
Self::ExclamationMarkTildeAsterisk => {}
Self::DoubleTilde => {}
Self::DoubleTildeAsterisk => {}
Self::ExclamationMarkDoubleTilde => {}
Self::ExclamationMarkDoubleTildeAsterisk => {}
Self::ShiftLeft => {}
Self::ShiftRight => {}
Self::Overlap => {}
Self::ExclamationMark => {}
Self::DoubleExclamationMark => {}
Self::AtSign => {}
Self::CaretAt => {}
Self::PGSquareRoot => {}
Self::PGCubeRoot => {}
Self::Placeholder(_0) => {
sqlparser::ast::Visit::visit(_0, visitor)?;
}
Self::Arrow => {}
Self::LongArrow => {}
Self::HashArrow => {}
Self::AtDashAt => {}
Self::QuestionMarkDash => {}
Self::AmpersandLeftAngleBracket => {}
Self::AmpersandRightAngleBracket => {}
Self::AmpersandLeftAngleBracketVerticalBar => {}
Self::VerticalBarAmpersandRightAngleBracket => {}
Self::TwoWayArrow => {}
Self::LeftAngleBracketCaret => {}
Self::RightAngleBracketCaret => {}
Self::QuestionMarkSharp => {}
Self::QuestionMarkDashVerticalBar => {}
Self::QuestionMarkDoubleVerticalBar => {}
Self::TildeEqual => {}
Self::ShiftLeftVerticalBar => {}
Self::VerticalBarShiftRight => {}
Self::VerticalBarRightAngleBracket => {}
Self::HashLongArrow => {}
Self::AtArrow => {}
Self::ArrowAt => {}
Self::HashMinus => {}
Self::AtQuestion => {}
Self::AtAt => {}
Self::Question => {}
Self::QuestionAnd => {}
Self::QuestionPipe => {}
Self::CustomBinaryOperator(_0) => {
sqlparser::ast::Visit::visit(_0, visitor)?;
}
}
::std::ops::ControlFlow::Continue(())
}
})
}
}Visit, impl sqlparser::ast::VisitMut for Token {
fn visit<V: sqlparser::ast::VisitorMut>(&mut self, visitor: &mut V)
-> ::std::ops::ControlFlow<V::Break> {
::recursive::__impl::stacker::maybe_grow(::recursive::get_minimum_stack_size(),
::recursive::get_stack_allocation_size(),
move || -> ::std::ops::ControlFlow<V::Break>
{
{
match self {
Self::EOF => {}
Self::Word(_0) => {
sqlparser::ast::VisitMut::visit(_0, visitor)?;
}
Self::Number(_0, _1) => {
sqlparser::ast::VisitMut::visit(_0, visitor)?;
sqlparser::ast::VisitMut::visit(_1, visitor)?;
}
Self::Char(_0) => {
sqlparser::ast::VisitMut::visit(_0, visitor)?;
}
Self::SingleQuotedString(_0) => {
sqlparser::ast::VisitMut::visit(_0, visitor)?;
}
Self::DoubleQuotedString(_0) => {
sqlparser::ast::VisitMut::visit(_0, visitor)?;
}
Self::TripleSingleQuotedString(_0) => {
sqlparser::ast::VisitMut::visit(_0, visitor)?;
}
Self::TripleDoubleQuotedString(_0) => {
sqlparser::ast::VisitMut::visit(_0, visitor)?;
}
Self::DollarQuotedString(_0) => {
sqlparser::ast::VisitMut::visit(_0, visitor)?;
}
Self::SingleQuotedByteStringLiteral(_0) => {
sqlparser::ast::VisitMut::visit(_0, visitor)?;
}
Self::DoubleQuotedByteStringLiteral(_0) => {
sqlparser::ast::VisitMut::visit(_0, visitor)?;
}
Self::TripleSingleQuotedByteStringLiteral(_0) => {
sqlparser::ast::VisitMut::visit(_0, visitor)?;
}
Self::TripleDoubleQuotedByteStringLiteral(_0) => {
sqlparser::ast::VisitMut::visit(_0, visitor)?;
}
Self::SingleQuotedRawStringLiteral(_0) => {
sqlparser::ast::VisitMut::visit(_0, visitor)?;
}
Self::DoubleQuotedRawStringLiteral(_0) => {
sqlparser::ast::VisitMut::visit(_0, visitor)?;
}
Self::TripleSingleQuotedRawStringLiteral(_0) => {
sqlparser::ast::VisitMut::visit(_0, visitor)?;
}
Self::TripleDoubleQuotedRawStringLiteral(_0) => {
sqlparser::ast::VisitMut::visit(_0, visitor)?;
}
Self::NationalStringLiteral(_0) => {
sqlparser::ast::VisitMut::visit(_0, visitor)?;
}
Self::QuoteDelimitedStringLiteral(_0) => {
sqlparser::ast::VisitMut::visit(_0, visitor)?;
}
Self::NationalQuoteDelimitedStringLiteral(_0) => {
sqlparser::ast::VisitMut::visit(_0, visitor)?;
}
Self::EscapedStringLiteral(_0) => {
sqlparser::ast::VisitMut::visit(_0, visitor)?;
}
Self::UnicodeStringLiteral(_0) => {
sqlparser::ast::VisitMut::visit(_0, visitor)?;
}
Self::HexStringLiteral(_0) => {
sqlparser::ast::VisitMut::visit(_0, visitor)?;
}
Self::Comma => {}
Self::Whitespace(_0) => {
sqlparser::ast::VisitMut::visit(_0, visitor)?;
}
Self::DoubleEq => {}
Self::Eq => {}
Self::Neq => {}
Self::Lt => {}
Self::Gt => {}
Self::LtEq => {}
Self::GtEq => {}
Self::Spaceship => {}
Self::Plus => {}
Self::Minus => {}
Self::Mul => {}
Self::Div => {}
Self::DuckIntDiv => {}
Self::Mod => {}
Self::StringConcat => {}
Self::LParen => {}
Self::RParen => {}
Self::Period => {}
Self::Colon => {}
Self::DoubleColon => {}
Self::Assignment => {}
Self::SemiColon => {}
Self::Backslash => {}
Self::LBracket => {}
Self::RBracket => {}
Self::Ampersand => {}
Self::Pipe => {}
Self::Caret => {}
Self::LBrace => {}
Self::RBrace => {}
Self::RArrow => {}
Self::Sharp => {}
Self::DoubleSharp => {}
Self::Tilde => {}
Self::TildeAsterisk => {}
Self::ExclamationMarkTilde => {}
Self::ExclamationMarkTildeAsterisk => {}
Self::DoubleTilde => {}
Self::DoubleTildeAsterisk => {}
Self::ExclamationMarkDoubleTilde => {}
Self::ExclamationMarkDoubleTildeAsterisk => {}
Self::ShiftLeft => {}
Self::ShiftRight => {}
Self::Overlap => {}
Self::ExclamationMark => {}
Self::DoubleExclamationMark => {}
Self::AtSign => {}
Self::CaretAt => {}
Self::PGSquareRoot => {}
Self::PGCubeRoot => {}
Self::Placeholder(_0) => {
sqlparser::ast::VisitMut::visit(_0, visitor)?;
}
Self::Arrow => {}
Self::LongArrow => {}
Self::HashArrow => {}
Self::AtDashAt => {}
Self::QuestionMarkDash => {}
Self::AmpersandLeftAngleBracket => {}
Self::AmpersandRightAngleBracket => {}
Self::AmpersandLeftAngleBracketVerticalBar => {}
Self::VerticalBarAmpersandRightAngleBracket => {}
Self::TwoWayArrow => {}
Self::LeftAngleBracketCaret => {}
Self::RightAngleBracketCaret => {}
Self::QuestionMarkSharp => {}
Self::QuestionMarkDashVerticalBar => {}
Self::QuestionMarkDoubleVerticalBar => {}
Self::TildeEqual => {}
Self::ShiftLeftVerticalBar => {}
Self::VerticalBarShiftRight => {}
Self::VerticalBarRightAngleBracket => {}
Self::HashLongArrow => {}
Self::AtArrow => {}
Self::ArrowAt => {}
Self::HashMinus => {}
Self::AtQuestion => {}
Self::AtAt => {}
Self::Question => {}
Self::QuestionAnd => {}
Self::QuestionPipe => {}
Self::CustomBinaryOperator(_0) => {
sqlparser::ast::VisitMut::visit(_0, visitor)?;
}
}
::std::ops::ControlFlow::Continue(())
}
})
}
}VisitMut))]
58pub enum Token {
59 EOF,
61 Word(Word),
63 Number(String, bool),
65 Char(char),
67 SingleQuotedString(String),
69 DoubleQuotedString(String),
71 TripleSingleQuotedString(String),
74 TripleDoubleQuotedString(String),
77 DollarQuotedString(DollarQuotedString),
79 SingleQuotedByteStringLiteral(String),
82 DoubleQuotedByteStringLiteral(String),
84 TripleSingleQuotedByteStringLiteral(String),
87 TripleDoubleQuotedByteStringLiteral(String),
90 SingleQuotedRawStringLiteral(String),
93 DoubleQuotedRawStringLiteral(String),
96 TripleSingleQuotedRawStringLiteral(String),
99 TripleDoubleQuotedRawStringLiteral(String),
102 NationalStringLiteral(String),
104 QuoteDelimitedStringLiteral(QuoteDelimitedString),
107 NationalQuoteDelimitedStringLiteral(QuoteDelimitedString),
110 EscapedStringLiteral(String),
112 UnicodeStringLiteral(String),
114 HexStringLiteral(String),
116 Comma,
118 Whitespace(Whitespace),
120 DoubleEq,
122 Eq,
124 Neq,
126 Lt,
128 Gt,
130 LtEq,
132 GtEq,
134 Spaceship,
136 Plus,
138 Minus,
140 Mul,
142 Div,
144 DuckIntDiv,
146 Mod,
148 StringConcat,
150 LParen,
152 RParen,
154 Period,
156 Colon,
158 DoubleColon,
160 Assignment,
162 SemiColon,
164 Backslash,
166 LBracket,
168 RBracket,
170 Ampersand,
172 Pipe,
174 Caret,
176 LBrace,
178 RBrace,
180 RArrow,
182 Sharp,
184 DoubleSharp,
186 Tilde,
188 TildeAsterisk,
190 ExclamationMarkTilde,
192 ExclamationMarkTildeAsterisk,
194 DoubleTilde,
196 DoubleTildeAsterisk,
198 ExclamationMarkDoubleTilde,
200 ExclamationMarkDoubleTildeAsterisk,
202 ShiftLeft,
204 ShiftRight,
206 Overlap,
208 ExclamationMark,
210 DoubleExclamationMark,
212 AtSign,
214 CaretAt,
216 PGSquareRoot,
218 PGCubeRoot,
220 Placeholder(String),
222 Arrow,
224 LongArrow,
226 HashArrow,
228 AtDashAt,
230 QuestionMarkDash,
232 AmpersandLeftAngleBracket,
234 AmpersandRightAngleBracket,
236 AmpersandLeftAngleBracketVerticalBar,
238 VerticalBarAmpersandRightAngleBracket,
240 TwoWayArrow,
242 LeftAngleBracketCaret,
244 RightAngleBracketCaret,
246 QuestionMarkSharp,
248 QuestionMarkDashVerticalBar,
250 QuestionMarkDoubleVerticalBar,
252 TildeEqual,
254 ShiftLeftVerticalBar,
256 VerticalBarShiftRight,
258 VerticalBarRightAngleBracket,
260 HashLongArrow,
262 AtArrow,
264 ArrowAt,
266 HashMinus,
269 AtQuestion,
272 AtAt,
276 Question,
279 QuestionAnd,
282 QuestionPipe,
285 CustomBinaryOperator(String),
289}
290
291impl fmt::Display for Token {
292 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
293 match self {
294 Token::EOF => f.write_str("EOF"),
295 Token::Word(ref w) => f.write_fmt(format_args!("{0}", w))write!(f, "{w}"),
296 Token::Number(ref n, l) => f.write_fmt(format_args!("{0}{1}", n, if *l { "L" } else { "" }))write!(f, "{}{long}", n, long = if *l { "L" } else { "" }),
297 Token::Char(ref c) => f.write_fmt(format_args!("{0}", c))write!(f, "{c}"),
298 Token::SingleQuotedString(ref s) => f.write_fmt(format_args!("\'{0}\'", s))write!(f, "'{s}'"),
299 Token::TripleSingleQuotedString(ref s) => f.write_fmt(format_args!("\'\'\'{0}\'\'\'", s))write!(f, "'''{s}'''"),
300 Token::DoubleQuotedString(ref s) => f.write_fmt(format_args!("\"{0}\"", s))write!(f, "\"{s}\""),
301 Token::TripleDoubleQuotedString(ref s) => f.write_fmt(format_args!("\"\"\"{0}\"\"\"", s))write!(f, "\"\"\"{s}\"\"\""),
302 Token::DollarQuotedString(ref s) => f.write_fmt(format_args!("{0}", s))write!(f, "{s}"),
303 Token::NationalStringLiteral(ref s) => f.write_fmt(format_args!("N\'{0}\'", s))write!(f, "N'{s}'"),
304 Token::QuoteDelimitedStringLiteral(ref s) => s.fmt(f),
305 Token::NationalQuoteDelimitedStringLiteral(ref s) => f.write_fmt(format_args!("N{0}", s))write!(f, "N{s}"),
306 Token::EscapedStringLiteral(ref s) => f.write_fmt(format_args!("E\'{0}\'", s))write!(f, "E'{s}'"),
307 Token::UnicodeStringLiteral(ref s) => f.write_fmt(format_args!("U&\'{0}\'", s))write!(f, "U&'{s}'"),
308 Token::HexStringLiteral(ref s) => f.write_fmt(format_args!("X\'{0}\'", s))write!(f, "X'{s}'"),
309 Token::SingleQuotedByteStringLiteral(ref s) => f.write_fmt(format_args!("B\'{0}\'", s))write!(f, "B'{s}'"),
310 Token::TripleSingleQuotedByteStringLiteral(ref s) => f.write_fmt(format_args!("B\'\'\'{0}\'\'\'", s))write!(f, "B'''{s}'''"),
311 Token::DoubleQuotedByteStringLiteral(ref s) => f.write_fmt(format_args!("B\"{0}\"", s))write!(f, "B\"{s}\""),
312 Token::TripleDoubleQuotedByteStringLiteral(ref s) => f.write_fmt(format_args!("B\"\"\"{0}\"\"\"", s))write!(f, "B\"\"\"{s}\"\"\""),
313 Token::SingleQuotedRawStringLiteral(ref s) => f.write_fmt(format_args!("R\'{0}\'", s))write!(f, "R'{s}'"),
314 Token::DoubleQuotedRawStringLiteral(ref s) => f.write_fmt(format_args!("R\"{0}\"", s))write!(f, "R\"{s}\""),
315 Token::TripleSingleQuotedRawStringLiteral(ref s) => f.write_fmt(format_args!("R\'\'\'{0}\'\'\'", s))write!(f, "R'''{s}'''"),
316 Token::TripleDoubleQuotedRawStringLiteral(ref s) => f.write_fmt(format_args!("R\"\"\"{0}\"\"\"", s))write!(f, "R\"\"\"{s}\"\"\""),
317 Token::Comma => f.write_str(","),
318 Token::Whitespace(ws) => f.write_fmt(format_args!("{0}", ws))write!(f, "{ws}"),
319 Token::DoubleEq => f.write_str("=="),
320 Token::Spaceship => f.write_str("<=>"),
321 Token::Eq => f.write_str("="),
322 Token::Neq => f.write_str("<>"),
323 Token::Lt => f.write_str("<"),
324 Token::Gt => f.write_str(">"),
325 Token::LtEq => f.write_str("<="),
326 Token::GtEq => f.write_str(">="),
327 Token::Plus => f.write_str("+"),
328 Token::Minus => f.write_str("-"),
329 Token::Mul => f.write_str("*"),
330 Token::Div => f.write_str("/"),
331 Token::DuckIntDiv => f.write_str("//"),
332 Token::StringConcat => f.write_str("||"),
333 Token::Mod => f.write_str("%"),
334 Token::LParen => f.write_str("("),
335 Token::RParen => f.write_str(")"),
336 Token::Period => f.write_str("."),
337 Token::Colon => f.write_str(":"),
338 Token::DoubleColon => f.write_str("::"),
339 Token::Assignment => f.write_str(":="),
340 Token::SemiColon => f.write_str(";"),
341 Token::Backslash => f.write_str("\\"),
342 Token::LBracket => f.write_str("["),
343 Token::RBracket => f.write_str("]"),
344 Token::Ampersand => f.write_str("&"),
345 Token::Caret => f.write_str("^"),
346 Token::Pipe => f.write_str("|"),
347 Token::LBrace => f.write_str("{"),
348 Token::RBrace => f.write_str("}"),
349 Token::RArrow => f.write_str("=>"),
350 Token::Sharp => f.write_str("#"),
351 Token::DoubleSharp => f.write_str("##"),
352 Token::ExclamationMark => f.write_str("!"),
353 Token::DoubleExclamationMark => f.write_str("!!"),
354 Token::Tilde => f.write_str("~"),
355 Token::TildeAsterisk => f.write_str("~*"),
356 Token::ExclamationMarkTilde => f.write_str("!~"),
357 Token::ExclamationMarkTildeAsterisk => f.write_str("!~*"),
358 Token::DoubleTilde => f.write_str("~~"),
359 Token::DoubleTildeAsterisk => f.write_str("~~*"),
360 Token::ExclamationMarkDoubleTilde => f.write_str("!~~"),
361 Token::ExclamationMarkDoubleTildeAsterisk => f.write_str("!~~*"),
362 Token::AtSign => f.write_str("@"),
363 Token::CaretAt => f.write_str("^@"),
364 Token::ShiftLeft => f.write_str("<<"),
365 Token::ShiftRight => f.write_str(">>"),
366 Token::Overlap => f.write_str("&&"),
367 Token::PGSquareRoot => f.write_str("|/"),
368 Token::PGCubeRoot => f.write_str("||/"),
369 Token::AtDashAt => f.write_str("@-@"),
370 Token::QuestionMarkDash => f.write_str("?-"),
371 Token::AmpersandLeftAngleBracket => f.write_str("&<"),
372 Token::AmpersandRightAngleBracket => f.write_str("&>"),
373 Token::AmpersandLeftAngleBracketVerticalBar => f.write_str("&<|"),
374 Token::VerticalBarAmpersandRightAngleBracket => f.write_str("|&>"),
375 Token::VerticalBarRightAngleBracket => f.write_str("|>"),
376 Token::TwoWayArrow => f.write_str("<->"),
377 Token::LeftAngleBracketCaret => f.write_str("<^"),
378 Token::RightAngleBracketCaret => f.write_str(">^"),
379 Token::QuestionMarkSharp => f.write_str("?#"),
380 Token::QuestionMarkDashVerticalBar => f.write_str("?-|"),
381 Token::QuestionMarkDoubleVerticalBar => f.write_str("?||"),
382 Token::TildeEqual => f.write_str("~="),
383 Token::ShiftLeftVerticalBar => f.write_str("<<|"),
384 Token::VerticalBarShiftRight => f.write_str("|>>"),
385 Token::Placeholder(ref s) => f.write_fmt(format_args!("{0}", s))write!(f, "{s}"),
386 Token::Arrow => f.write_fmt(format_args!("->"))write!(f, "->"),
387 Token::LongArrow => f.write_fmt(format_args!("->>"))write!(f, "->>"),
388 Token::HashArrow => f.write_fmt(format_args!("#>"))write!(f, "#>"),
389 Token::HashLongArrow => f.write_fmt(format_args!("#>>"))write!(f, "#>>"),
390 Token::AtArrow => f.write_fmt(format_args!("@>"))write!(f, "@>"),
391 Token::ArrowAt => f.write_fmt(format_args!("<@"))write!(f, "<@"),
392 Token::HashMinus => f.write_fmt(format_args!("#-"))write!(f, "#-"),
393 Token::AtQuestion => f.write_fmt(format_args!("@?"))write!(f, "@?"),
394 Token::AtAt => f.write_fmt(format_args!("@@"))write!(f, "@@"),
395 Token::Question => f.write_fmt(format_args!("?"))write!(f, "?"),
396 Token::QuestionAnd => f.write_fmt(format_args!("?&"))write!(f, "?&"),
397 Token::QuestionPipe => f.write_fmt(format_args!("?|"))write!(f, "?|"),
398 Token::CustomBinaryOperator(s) => f.write_str(s),
399 }
400 }
401}
402
403impl Token {
404 pub fn make_keyword(keyword: &str) -> Self {
408 Token::make_word(keyword, None)
409 }
410
411 pub fn make_word(word: &str, quote_style: Option<char>) -> Self {
416 let keyword = if quote_style.is_none() {
420 let word_uppercase = word.to_ascii_uppercase();
421 ALL_KEYWORDS
422 .binary_search(&word_uppercase.as_str())
423 .map_or(Keyword::NoKeyword, |x| ALL_KEYWORDS_INDEX[x])
424 } else {
425 Keyword::NoKeyword
426 };
427
428 Token::Word(Word {
429 value: word.to_string(),
430 quote_style,
431 keyword,
432 })
433 }
434}
435
436#[derive(#[automatically_derived]
impl ::core::fmt::Debug for Word {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field3_finish(f, "Word", "value",
&self.value, "quote_style", &self.quote_style, "keyword",
&&self.keyword)
}
}Debug, #[automatically_derived]
impl ::core::clone::Clone for Word {
#[inline]
fn clone(&self) -> Word {
Word {
value: ::core::clone::Clone::clone(&self.value),
quote_style: ::core::clone::Clone::clone(&self.quote_style),
keyword: ::core::clone::Clone::clone(&self.keyword),
}
}
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for Word {
#[inline]
fn eq(&self, other: &Word) -> bool {
self.value == other.value && self.quote_style == other.quote_style &&
self.keyword == other.keyword
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::PartialOrd for Word {
#[inline]
fn partial_cmp(&self, other: &Word)
-> ::core::option::Option<::core::cmp::Ordering> {
match ::core::cmp::PartialOrd::partial_cmp(&self.value, &other.value)
{
::core::option::Option::Some(::core::cmp::Ordering::Equal) =>
match ::core::cmp::PartialOrd::partial_cmp(&self.quote_style,
&other.quote_style) {
::core::option::Option::Some(::core::cmp::Ordering::Equal)
=>
::core::cmp::PartialOrd::partial_cmp(&self.keyword,
&other.keyword),
cmp => cmp,
},
cmp => cmp,
}
}
}PartialOrd, #[automatically_derived]
impl ::core::cmp::Eq for Word {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<String>;
let _: ::core::cmp::AssertParamIsEq<Option<char>>;
let _: ::core::cmp::AssertParamIsEq<Keyword>;
}
}Eq, #[automatically_derived]
impl ::core::cmp::Ord for Word {
#[inline]
fn cmp(&self, other: &Word) -> ::core::cmp::Ordering {
match ::core::cmp::Ord::cmp(&self.value, &other.value) {
::core::cmp::Ordering::Equal =>
match ::core::cmp::Ord::cmp(&self.quote_style,
&other.quote_style) {
::core::cmp::Ordering::Equal =>
::core::cmp::Ord::cmp(&self.keyword, &other.keyword),
cmp => cmp,
},
cmp => cmp,
}
}
}Ord, #[automatically_derived]
impl ::core::hash::Hash for Word {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.value, state);
::core::hash::Hash::hash(&self.quote_style, state);
::core::hash::Hash::hash(&self.keyword, state)
}
}Hash)]
438#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
439#[cfg_attr(feature = "visitor", derive(impl sqlparser::ast::Visit for Word {
fn visit<V: sqlparser::ast::Visitor>(&self, visitor: &mut V)
-> ::std::ops::ControlFlow<V::Break> {
::recursive::__impl::stacker::maybe_grow(::recursive::get_minimum_stack_size(),
::recursive::get_stack_allocation_size(),
move || -> ::std::ops::ControlFlow<V::Break>
{
{
sqlparser::ast::Visit::visit(&self.value, visitor)?;
sqlparser::ast::Visit::visit(&self.quote_style, visitor)?;
sqlparser::ast::Visit::visit(&self.keyword, visitor)?;
::std::ops::ControlFlow::Continue(())
}
})
}
}Visit, impl sqlparser::ast::VisitMut for Word {
fn visit<V: sqlparser::ast::VisitorMut>(&mut self, visitor: &mut V)
-> ::std::ops::ControlFlow<V::Break> {
::recursive::__impl::stacker::maybe_grow(::recursive::get_minimum_stack_size(),
::recursive::get_stack_allocation_size(),
move || -> ::std::ops::ControlFlow<V::Break>
{
{
sqlparser::ast::VisitMut::visit(&mut self.value, visitor)?;
sqlparser::ast::VisitMut::visit(&mut self.quote_style,
visitor)?;
sqlparser::ast::VisitMut::visit(&mut self.keyword,
visitor)?;
::std::ops::ControlFlow::Continue(())
}
})
}
}VisitMut))]
440pub struct Word {
441 pub value: String,
444 pub quote_style: Option<char>,
448 pub keyword: Keyword,
451}
452
453impl fmt::Display for Word {
454 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
455 match self.quote_style {
456 Some(s) if s == '"' || s == '[' || s == '`' => {
457 f.write_fmt(format_args!("{0}{1}{2}", s, self.value,
Word::matching_end_quote(s)))write!(f, "{}{}{}", s, self.value, Word::matching_end_quote(s))
458 }
459 None => f.write_str(&self.value),
460 _ => { ::core::panicking::panic_fmt(format_args!("Unexpected quote_style!")); }panic!("Unexpected quote_style!"),
461 }
462 }
463}
464
465impl Word {
466 fn matching_end_quote(ch: char) -> char {
467 match ch {
468 '"' => '"', '[' => ']', '`' => '`', _ => { ::core::panicking::panic_fmt(format_args!("unexpected quoting style!")); }panic!("unexpected quoting style!"),
472 }
473 }
474}
475
476#[derive(#[automatically_derived]
impl ::core::fmt::Debug for Whitespace {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
Whitespace::Space =>
::core::fmt::Formatter::write_str(f, "Space"),
Whitespace::Newline =>
::core::fmt::Formatter::write_str(f, "Newline"),
Whitespace::Tab => ::core::fmt::Formatter::write_str(f, "Tab"),
Whitespace::SingleLineComment {
comment: __self_0, prefix: __self_1 } =>
::core::fmt::Formatter::debug_struct_field2_finish(f,
"SingleLineComment", "comment", __self_0, "prefix",
&__self_1),
Whitespace::MultiLineComment(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"MultiLineComment", &__self_0),
}
}
}Debug, #[automatically_derived]
impl ::core::clone::Clone for Whitespace {
#[inline]
fn clone(&self) -> Whitespace {
match self {
Whitespace::Space => Whitespace::Space,
Whitespace::Newline => Whitespace::Newline,
Whitespace::Tab => Whitespace::Tab,
Whitespace::SingleLineComment {
comment: __self_0, prefix: __self_1 } =>
Whitespace::SingleLineComment {
comment: ::core::clone::Clone::clone(__self_0),
prefix: ::core::clone::Clone::clone(__self_1),
},
Whitespace::MultiLineComment(__self_0) =>
Whitespace::MultiLineComment(::core::clone::Clone::clone(__self_0)),
}
}
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for Whitespace {
#[inline]
fn eq(&self, other: &Whitespace) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr &&
match (self, other) {
(Whitespace::SingleLineComment {
comment: __self_0, prefix: __self_1 },
Whitespace::SingleLineComment {
comment: __arg1_0, prefix: __arg1_1 }) =>
__self_0 == __arg1_0 && __self_1 == __arg1_1,
(Whitespace::MultiLineComment(__self_0),
Whitespace::MultiLineComment(__arg1_0)) =>
__self_0 == __arg1_0,
_ => true,
}
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::PartialOrd for Whitespace {
#[inline]
fn partial_cmp(&self, other: &Whitespace)
-> ::core::option::Option<::core::cmp::Ordering> {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
match (self, other) {
(Whitespace::SingleLineComment {
comment: __self_0, prefix: __self_1 },
Whitespace::SingleLineComment {
comment: __arg1_0, prefix: __arg1_1 }) =>
match ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0)
{
::core::option::Option::Some(::core::cmp::Ordering::Equal)
=> ::core::cmp::PartialOrd::partial_cmp(__self_1, __arg1_1),
cmp => cmp,
},
(Whitespace::MultiLineComment(__self_0),
Whitespace::MultiLineComment(__arg1_0)) =>
::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
_ =>
::core::cmp::PartialOrd::partial_cmp(&__self_discr,
&__arg1_discr),
}
}
}PartialOrd, #[automatically_derived]
impl ::core::cmp::Eq for Whitespace {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<String>;
}
}Eq, #[automatically_derived]
impl ::core::cmp::Ord for Whitespace {
#[inline]
fn cmp(&self, other: &Whitespace) -> ::core::cmp::Ordering {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
match ::core::cmp::Ord::cmp(&__self_discr, &__arg1_discr) {
::core::cmp::Ordering::Equal =>
match (self, other) {
(Whitespace::SingleLineComment {
comment: __self_0, prefix: __self_1 },
Whitespace::SingleLineComment {
comment: __arg1_0, prefix: __arg1_1 }) =>
match ::core::cmp::Ord::cmp(__self_0, __arg1_0) {
::core::cmp::Ordering::Equal =>
::core::cmp::Ord::cmp(__self_1, __arg1_1),
cmp => cmp,
},
(Whitespace::MultiLineComment(__self_0),
Whitespace::MultiLineComment(__arg1_0)) =>
::core::cmp::Ord::cmp(__self_0, __arg1_0),
_ => ::core::cmp::Ordering::Equal,
},
cmp => cmp,
}
}
}Ord, #[automatically_derived]
impl ::core::hash::Hash for Whitespace {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
let __self_discr = ::core::intrinsics::discriminant_value(self);
::core::hash::Hash::hash(&__self_discr, state);
match self {
Whitespace::SingleLineComment {
comment: __self_0, prefix: __self_1 } => {
::core::hash::Hash::hash(__self_0, state);
::core::hash::Hash::hash(__self_1, state)
}
Whitespace::MultiLineComment(__self_0) =>
::core::hash::Hash::hash(__self_0, state),
_ => {}
}
}
}Hash)]
478#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
479#[cfg_attr(feature = "visitor", derive(impl sqlparser::ast::Visit for Whitespace {
fn visit<V: sqlparser::ast::Visitor>(&self, visitor: &mut V)
-> ::std::ops::ControlFlow<V::Break> {
::recursive::__impl::stacker::maybe_grow(::recursive::get_minimum_stack_size(),
::recursive::get_stack_allocation_size(),
move || -> ::std::ops::ControlFlow<V::Break>
{
{
match self {
Self::Space => {}
Self::Newline => {}
Self::Tab => {}
Self::SingleLineComment { comment, prefix } => {
sqlparser::ast::Visit::visit(comment, visitor)?;
sqlparser::ast::Visit::visit(prefix, visitor)?;
}
Self::MultiLineComment(_0) => {
sqlparser::ast::Visit::visit(_0, visitor)?;
}
}
::std::ops::ControlFlow::Continue(())
}
})
}
}Visit, impl sqlparser::ast::VisitMut for Whitespace {
fn visit<V: sqlparser::ast::VisitorMut>(&mut self, visitor: &mut V)
-> ::std::ops::ControlFlow<V::Break> {
::recursive::__impl::stacker::maybe_grow(::recursive::get_minimum_stack_size(),
::recursive::get_stack_allocation_size(),
move || -> ::std::ops::ControlFlow<V::Break>
{
{
match self {
Self::Space => {}
Self::Newline => {}
Self::Tab => {}
Self::SingleLineComment { comment, prefix } => {
sqlparser::ast::VisitMut::visit(comment, visitor)?;
sqlparser::ast::VisitMut::visit(prefix, visitor)?;
}
Self::MultiLineComment(_0) => {
sqlparser::ast::VisitMut::visit(_0, visitor)?;
}
}
::std::ops::ControlFlow::Continue(())
}
})
}
}VisitMut))]
480pub enum Whitespace {
481 Space,
483 Newline,
485 Tab,
487 SingleLineComment {
490 comment: String,
492 prefix: String,
494 },
495
496 MultiLineComment(String),
498}
499
500impl fmt::Display for Whitespace {
501 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
502 match self {
503 Whitespace::Space => f.write_str(" "),
504 Whitespace::Newline => f.write_str("\n"),
505 Whitespace::Tab => f.write_str("\t"),
506 Whitespace::SingleLineComment { prefix, comment } => f.write_fmt(format_args!("{0}{1}", prefix, comment))write!(f, "{prefix}{comment}"),
507 Whitespace::MultiLineComment(s) => f.write_fmt(format_args!("/*{0}*/", s))write!(f, "/*{s}*/"),
508 }
509 }
510}
511
512#[derive(#[automatically_derived]
impl ::core::cmp::Eq for Location {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<u64>;
}
}Eq, #[automatically_derived]
impl ::core::cmp::PartialEq for Location {
#[inline]
fn eq(&self, other: &Location) -> bool {
self.line == other.line && self.column == other.column
}
}PartialEq, #[automatically_derived]
impl ::core::hash::Hash for Location {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.line, state);
::core::hash::Hash::hash(&self.column, state)
}
}Hash, #[automatically_derived]
impl ::core::clone::Clone for Location {
#[inline]
fn clone(&self) -> Location {
let _: ::core::clone::AssertParamIsClone<u64>;
*self
}
}Clone, #[automatically_derived]
impl ::core::marker::Copy for Location { }Copy, #[automatically_derived]
impl ::core::cmp::Ord for Location {
#[inline]
fn cmp(&self, other: &Location) -> ::core::cmp::Ordering {
match ::core::cmp::Ord::cmp(&self.line, &other.line) {
::core::cmp::Ordering::Equal =>
::core::cmp::Ord::cmp(&self.column, &other.column),
cmp => cmp,
}
}
}Ord, #[automatically_derived]
impl ::core::cmp::PartialOrd for Location {
#[inline]
fn partial_cmp(&self, other: &Location)
-> ::core::option::Option<::core::cmp::Ordering> {
match ::core::cmp::PartialOrd::partial_cmp(&self.line, &other.line) {
::core::option::Option::Some(::core::cmp::Ordering::Equal) =>
::core::cmp::PartialOrd::partial_cmp(&self.column,
&other.column),
cmp => cmp,
}
}
}PartialOrd)]
532#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
533#[cfg_attr(feature = "visitor", derive(impl sqlparser::ast::Visit for Location {
fn visit<V: sqlparser::ast::Visitor>(&self, visitor: &mut V)
-> ::std::ops::ControlFlow<V::Break> {
::recursive::__impl::stacker::maybe_grow(::recursive::get_minimum_stack_size(),
::recursive::get_stack_allocation_size(),
move || -> ::std::ops::ControlFlow<V::Break>
{
{
sqlparser::ast::Visit::visit(&self.line, visitor)?;
sqlparser::ast::Visit::visit(&self.column, visitor)?;
::std::ops::ControlFlow::Continue(())
}
})
}
}Visit, impl sqlparser::ast::VisitMut for Location {
fn visit<V: sqlparser::ast::VisitorMut>(&mut self, visitor: &mut V)
-> ::std::ops::ControlFlow<V::Break> {
::recursive::__impl::stacker::maybe_grow(::recursive::get_minimum_stack_size(),
::recursive::get_stack_allocation_size(),
move || -> ::std::ops::ControlFlow<V::Break>
{
{
sqlparser::ast::VisitMut::visit(&mut self.line, visitor)?;
sqlparser::ast::VisitMut::visit(&mut self.column, visitor)?;
::std::ops::ControlFlow::Continue(())
}
})
}
}VisitMut))]
534pub struct Location {
535 pub line: u64,
539 pub column: u64,
543}
544
545impl fmt::Display for Location {
546 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
547 if self.line == 0 {
548 return Ok(());
549 }
550 f.write_fmt(format_args!(" at Line: {0}, Column: {1}", self.line,
self.column))write!(f, " at Line: {}, Column: {}", self.line, self.column)
551 }
552}
553
554impl fmt::Debug for Location {
555 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
556 f.write_fmt(format_args!("Location({0},{1})", self.line, self.column))write!(f, "Location({},{})", self.line, self.column)
557 }
558}
559
560impl Location {
561 pub fn empty() -> Self {
563 Self { line: 0, column: 0 }
564 }
565
566 pub fn new(line: u64, column: u64) -> Self {
568 Self { line, column }
569 }
570
571 pub fn of(line: u64, column: u64) -> Self {
576 Self::new(line, column)
577 }
578
579 pub fn span_to(self, end: Self) -> Span {
581 Span { start: self, end }
582 }
583}
584
585impl From<(u64, u64)> for Location {
586 fn from((line, column): (u64, u64)) -> Self {
587 Self { line, column }
588 }
589}
590
591#[derive(#[automatically_derived]
impl ::core::cmp::Eq for Span {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<Location>;
}
}Eq, #[automatically_derived]
impl ::core::cmp::PartialEq for Span {
#[inline]
fn eq(&self, other: &Span) -> bool {
self.start == other.start && self.end == other.end
}
}PartialEq, #[automatically_derived]
impl ::core::hash::Hash for Span {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.start, state);
::core::hash::Hash::hash(&self.end, state)
}
}Hash, #[automatically_derived]
impl ::core::clone::Clone for Span {
#[inline]
fn clone(&self) -> Span {
let _: ::core::clone::AssertParamIsClone<Location>;
*self
}
}Clone, #[automatically_derived]
impl ::core::cmp::PartialOrd for Span {
#[inline]
fn partial_cmp(&self, other: &Span)
-> ::core::option::Option<::core::cmp::Ordering> {
match ::core::cmp::PartialOrd::partial_cmp(&self.start, &other.start)
{
::core::option::Option::Some(::core::cmp::Ordering::Equal) =>
::core::cmp::PartialOrd::partial_cmp(&self.end, &other.end),
cmp => cmp,
}
}
}PartialOrd, #[automatically_derived]
impl ::core::cmp::Ord for Span {
#[inline]
fn cmp(&self, other: &Span) -> ::core::cmp::Ordering {
match ::core::cmp::Ord::cmp(&self.start, &other.start) {
::core::cmp::Ordering::Equal =>
::core::cmp::Ord::cmp(&self.end, &other.end),
cmp => cmp,
}
}
}Ord, #[automatically_derived]
impl ::core::marker::Copy for Span { }Copy)]
595#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
596#[cfg_attr(feature = "visitor", derive(impl sqlparser::ast::Visit for Span {
fn visit<V: sqlparser::ast::Visitor>(&self, visitor: &mut V)
-> ::std::ops::ControlFlow<V::Break> {
::recursive::__impl::stacker::maybe_grow(::recursive::get_minimum_stack_size(),
::recursive::get_stack_allocation_size(),
move || -> ::std::ops::ControlFlow<V::Break>
{
{
sqlparser::ast::Visit::visit(&self.start, visitor)?;
sqlparser::ast::Visit::visit(&self.end, visitor)?;
::std::ops::ControlFlow::Continue(())
}
})
}
}Visit, impl sqlparser::ast::VisitMut for Span {
fn visit<V: sqlparser::ast::VisitorMut>(&mut self, visitor: &mut V)
-> ::std::ops::ControlFlow<V::Break> {
::recursive::__impl::stacker::maybe_grow(::recursive::get_minimum_stack_size(),
::recursive::get_stack_allocation_size(),
move || -> ::std::ops::ControlFlow<V::Break>
{
{
sqlparser::ast::VisitMut::visit(&mut self.start, visitor)?;
sqlparser::ast::VisitMut::visit(&mut self.end, visitor)?;
::std::ops::ControlFlow::Continue(())
}
})
}
}VisitMut))]
597pub struct Span {
598 pub start: Location,
600 pub end: Location,
602}
603
604impl fmt::Debug for Span {
605 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
606 f.write_fmt(format_args!("Span({0:?}..{1:?})", self.start, self.end))write!(f, "Span({:?}..{:?})", self.start, self.end)
607 }
608}
609
610impl Span {
611 const EMPTY: Span = Self::empty();
614
615 pub fn new(start: Location, end: Location) -> Span {
617 Span { start, end }
618 }
619
620 pub const fn empty() -> Span {
625 Span {
626 start: Location { line: 0, column: 0 },
627 end: Location { line: 0, column: 0 },
628 }
629 }
630
631 pub fn union(&self, other: &Span) -> Span {
647 match (self, other) {
650 (&Span::EMPTY, _) => *other,
651 (_, &Span::EMPTY) => *self,
652 _ => Span {
653 start: cmp::min(self.start, other.start),
654 end: cmp::max(self.end, other.end),
655 },
656 }
657 }
658
659 pub fn union_opt(&self, other: &Option<Span>) -> Span {
663 match other {
664 Some(other) => self.union(other),
665 None => *self,
666 }
667 }
668
669 pub fn union_iter<I: IntoIterator<Item = Span>>(iter: I) -> Span {
687 iter.into_iter()
688 .reduce(|acc, item| acc.union(&item))
689 .unwrap_or(Span::empty())
690 }
691}
692
693#[deprecated(since = "0.53.0", note = "please use `TokenWithSpan` instead")]
695pub type TokenWithLocation = TokenWithSpan;
696
697#[derive(#[automatically_derived]
impl ::core::fmt::Debug for TokenWithSpan {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f, "TokenWithSpan",
"token", &self.token, "span", &&self.span)
}
}Debug, #[automatically_derived]
impl ::core::clone::Clone for TokenWithSpan {
#[inline]
fn clone(&self) -> TokenWithSpan {
TokenWithSpan {
token: ::core::clone::Clone::clone(&self.token),
span: ::core::clone::Clone::clone(&self.span),
}
}
}Clone, #[automatically_derived]
impl ::core::hash::Hash for TokenWithSpan {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.token, state);
::core::hash::Hash::hash(&self.span, state)
}
}Hash, #[automatically_derived]
impl ::core::cmp::Ord for TokenWithSpan {
#[inline]
fn cmp(&self, other: &TokenWithSpan) -> ::core::cmp::Ordering {
match ::core::cmp::Ord::cmp(&self.token, &other.token) {
::core::cmp::Ordering::Equal =>
::core::cmp::Ord::cmp(&self.span, &other.span),
cmp => cmp,
}
}
}Ord, #[automatically_derived]
impl ::core::cmp::PartialOrd for TokenWithSpan {
#[inline]
fn partial_cmp(&self, other: &TokenWithSpan)
-> ::core::option::Option<::core::cmp::Ordering> {
match ::core::cmp::PartialOrd::partial_cmp(&self.token, &other.token)
{
::core::option::Option::Some(::core::cmp::Ordering::Equal) =>
::core::cmp::PartialOrd::partial_cmp(&self.span, &other.span),
cmp => cmp,
}
}
}PartialOrd, #[automatically_derived]
impl ::core::cmp::Eq for TokenWithSpan {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<Token>;
let _: ::core::cmp::AssertParamIsEq<Span>;
}
}Eq, #[automatically_derived]
impl ::core::cmp::PartialEq for TokenWithSpan {
#[inline]
fn eq(&self, other: &TokenWithSpan) -> bool {
self.token == other.token && self.span == other.span
}
}PartialEq)]
720#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
721#[cfg_attr(feature = "visitor", derive(impl sqlparser::ast::Visit for TokenWithSpan {
fn visit<V: sqlparser::ast::Visitor>(&self, visitor: &mut V)
-> ::std::ops::ControlFlow<V::Break> {
::recursive::__impl::stacker::maybe_grow(::recursive::get_minimum_stack_size(),
::recursive::get_stack_allocation_size(),
move || -> ::std::ops::ControlFlow<V::Break>
{
{
sqlparser::ast::Visit::visit(&self.token, visitor)?;
sqlparser::ast::Visit::visit(&self.span, visitor)?;
::std::ops::ControlFlow::Continue(())
}
})
}
}Visit, impl sqlparser::ast::VisitMut for TokenWithSpan {
fn visit<V: sqlparser::ast::VisitorMut>(&mut self, visitor: &mut V)
-> ::std::ops::ControlFlow<V::Break> {
::recursive::__impl::stacker::maybe_grow(::recursive::get_minimum_stack_size(),
::recursive::get_stack_allocation_size(),
move || -> ::std::ops::ControlFlow<V::Break>
{
{
sqlparser::ast::VisitMut::visit(&mut self.token, visitor)?;
sqlparser::ast::VisitMut::visit(&mut self.span, visitor)?;
::std::ops::ControlFlow::Continue(())
}
})
}
}VisitMut))]
722pub struct TokenWithSpan {
724 pub token: Token,
726 pub span: Span,
728}
729
730impl TokenWithSpan {
731 pub fn new(token: Token, span: Span) -> Self {
733 Self { token, span }
734 }
735
736 pub fn wrap(token: Token) -> Self {
738 Self::new(token, Span::empty())
739 }
740
741 pub fn at(token: Token, start: Location, end: Location) -> Self {
743 Self::new(token, Span::new(start, end))
744 }
745
746 pub fn new_eof() -> Self {
748 Self::wrap(Token::EOF)
749 }
750}
751
752impl PartialEq<Token> for TokenWithSpan {
753 fn eq(&self, other: &Token) -> bool {
754 &self.token == other
755 }
756}
757
758impl PartialEq<TokenWithSpan> for Token {
759 fn eq(&self, other: &TokenWithSpan) -> bool {
760 self == &other.token
761 }
762}
763
764impl fmt::Display for TokenWithSpan {
765 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
766 self.token.fmt(f)
767 }
768}
769
770#[derive(#[automatically_derived]
impl ::core::fmt::Debug for TokenizerError {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f,
"TokenizerError", "message", &self.message, "location",
&&self.location)
}
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for TokenizerError {
#[inline]
fn eq(&self, other: &TokenizerError) -> bool {
self.message == other.message && self.location == other.location
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for TokenizerError {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<String>;
let _: ::core::cmp::AssertParamIsEq<Location>;
}
}Eq)]
772pub struct TokenizerError {
773 pub message: String,
775 pub location: Location,
777}
778
779impl fmt::Display for TokenizerError {
780 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
781 f.write_fmt(format_args!("{0}{1}", self.message, self.location))write!(f, "{}{}", self.message, self.location,)
782 }
783}
784
785impl core::error::Error for TokenizerError {}
786
787struct State<'a> {
788 peekable: Peekable<Chars<'a>>,
789 line: u64,
790 col: u64,
791}
792
793impl State<'_> {
794 pub fn next(&mut self) -> Option<char> {
796 match self.peekable.next() {
797 None => None,
798 Some(s) => {
799 if s == '\n' {
800 self.line += 1;
801 self.col = 1;
802 } else {
803 self.col += 1;
804 }
805 Some(s)
806 }
807 }
808 }
809
810 pub fn peek(&mut self) -> Option<&char> {
812 self.peekable.peek()
813 }
814
815 pub fn location(&self) -> Location {
817 Location {
818 line: self.line,
819 column: self.col,
820 }
821 }
822}
823
824#[derive(#[automatically_derived]
impl ::core::marker::Copy for NumStringQuoteChars { }Copy, #[automatically_derived]
impl ::core::clone::Clone for NumStringQuoteChars {
#[inline]
fn clone(&self) -> NumStringQuoteChars {
let _: ::core::clone::AssertParamIsClone<NonZeroU8>;
*self
}
}Clone)]
826enum NumStringQuoteChars {
827 One,
829 Many(NonZeroU8),
831}
832
833struct TokenizeQuotedStringSettings {
835 quote_style: char,
837 num_quote_chars: NumStringQuoteChars,
839 num_opening_quotes_to_consume: u8,
845 backslash_escape: bool,
848}
849
850pub struct Tokenizer<'a> {
852 dialect: &'a dyn Dialect,
853 query: &'a str,
854 unescape: bool,
857}
858
859impl<'a> Tokenizer<'a> {
860 pub fn new(dialect: &'a dyn Dialect, query: &'a str) -> Self {
877 Self {
878 dialect,
879 query,
880 unescape: true,
881 }
882 }
883
884 pub fn with_unescape(mut self, unescape: bool) -> Self {
915 self.unescape = unescape;
916 self
917 }
918
919 pub fn tokenize(&mut self) -> Result<Vec<Token>, TokenizerError> {
921 let twl = self.tokenize_with_location()?;
922 Ok(twl.into_iter().map(|t| t.token).collect())
923 }
924
925 pub fn tokenize_with_location(&mut self) -> Result<Vec<TokenWithSpan>, TokenizerError> {
927 let mut tokens: Vec<TokenWithSpan> = ::alloc::vec::Vec::new()vec![];
928 self.tokenize_with_location_into_buf(&mut tokens)
929 .map(|_| tokens)
930 }
931
932 pub fn tokenize_with_location_into_buf(
935 &mut self,
936 buf: &mut Vec<TokenWithSpan>,
937 ) -> Result<(), TokenizerError> {
938 self.tokenize_with_location_into_buf_with_mapper(buf, |token| token)
939 }
940
941 pub fn tokenize_with_location_into_buf_with_mapper(
944 &mut self,
945 buf: &mut Vec<TokenWithSpan>,
946 mut mapper: impl FnMut(TokenWithSpan) -> TokenWithSpan,
947 ) -> Result<(), TokenizerError> {
948 let mut state = State {
949 peekable: self.query.chars().peekable(),
950 line: 1,
951 col: 1,
952 };
953
954 let mut location = state.location();
955 while let Some(token) = self.next_token(&mut state, buf.last().map(|t| &t.token))? {
956 let span = location.span_to(state.location());
957
958 match &token {
960 Token::Whitespace(Whitespace::MultiLineComment(comment))
961 if self.dialect.supports_multiline_comment_hints()
962 && comment.starts_with('!') =>
963 {
964 self.tokenize_comment_hints(comment, span, buf, &mut mapper)?;
966 }
967 _ => {
968 buf.push(mapper(TokenWithSpan { token, span }));
969 }
970 }
971
972 location = state.location();
973 }
974 Ok(())
975 }
976
977 fn tokenize_comment_hints(
980 &self,
981 comment: &str,
982 span: Span,
983 buf: &mut Vec<TokenWithSpan>,
984 mut mapper: impl FnMut(TokenWithSpan) -> TokenWithSpan,
985 ) -> Result<(), TokenizerError> {
986 let hint_content = comment
988 .strip_prefix('!')
989 .unwrap_or(comment)
990 .trim_start_matches(|c: char| c.is_ascii_digit());
991
992 if hint_content.is_empty() {
994 return Ok(());
995 }
996
997 let inner = Tokenizer::new(self.dialect, hint_content).with_unescape(self.unescape);
999
1000 let mut state = State {
1002 peekable: hint_content.chars().peekable(),
1003 line: span.start.line,
1004 col: span.start.column,
1005 };
1006
1007 let mut location = state.location();
1009 while let Some(token) = inner.next_token(&mut state, buf.last().map(|t| &t.token))? {
1010 let token_span = location.span_to(state.location());
1011 buf.push(mapper(TokenWithSpan {
1012 token,
1013 span: token_span,
1014 }));
1015 location = state.location();
1016 }
1017
1018 Ok(())
1019 }
1020
1021 fn tokenize_identifier_or_keyword(
1023 &self,
1024 ch: impl IntoIterator<Item = char>,
1025 chars: &mut State,
1026 ) -> Result<Option<Token>, TokenizerError> {
1027 chars.next(); let ch: String = ch.into_iter().collect();
1029 let word = self.tokenize_word(ch, chars);
1030
1031 if word.chars().all(|x| x.is_ascii_digit() || x == '.') {
1033 let mut inner_state = State {
1034 peekable: word.chars().peekable(),
1035 line: 0,
1036 col: 0,
1037 };
1038 let mut s = peeking_take_while(&mut inner_state, |ch| #[allow(non_exhaustive_omitted_patterns)] match ch {
'0'..='9' | '.' => true,
_ => false,
}matches!(ch, '0'..='9' | '.'));
1039 let s2 = peeking_take_while(chars, |ch| #[allow(non_exhaustive_omitted_patterns)] match ch {
'0'..='9' | '.' => true,
_ => false,
}matches!(ch, '0'..='9' | '.'));
1040 s += s2.as_str();
1041 return Ok(Some(Token::Number(s, false)));
1042 }
1043
1044 Ok(Some(Token::make_word(&word, None)))
1045 }
1046
1047 fn next_token(
1049 &self,
1050 chars: &mut State,
1051 prev_token: Option<&Token>,
1052 ) -> Result<Option<Token>, TokenizerError> {
1053 match chars.peek() {
1054 Some(&ch) => match ch {
1055 ' ' => self.consume_and_return(chars, Token::Whitespace(Whitespace::Space)),
1056 '\t' => self.consume_and_return(chars, Token::Whitespace(Whitespace::Tab)),
1057 '\n' => self.consume_and_return(chars, Token::Whitespace(Whitespace::Newline)),
1058 '\r' => {
1059 chars.next();
1061 if let Some('\n') = chars.peek() {
1062 chars.next();
1063 }
1064 Ok(Some(Token::Whitespace(Whitespace::Newline)))
1065 }
1066 b @ 'B' | b @ 'b' if (self.dialect.is::<BigQueryDialect>() ||
self.dialect.is::<PostgreSqlDialect>() ||
self.dialect.is::<MySqlDialect>() ||
self.dialect.is::<GenericDialect>())dialect_of!(self is BigQueryDialect | PostgreSqlDialect | MySqlDialect | GenericDialect) =>
1068 {
1069 chars.next(); match chars.peek() {
1071 Some('\'') => {
1072 if self.dialect.supports_triple_quoted_string() {
1073 return self
1074 .tokenize_single_or_triple_quoted_string::<fn(String) -> Token>(
1075 chars,
1076 '\'',
1077 false,
1078 Token::SingleQuotedByteStringLiteral,
1079 Token::TripleSingleQuotedByteStringLiteral,
1080 );
1081 }
1082 let s = self.tokenize_single_quoted_string(chars, '\'', false)?;
1083 Ok(Some(Token::SingleQuotedByteStringLiteral(s)))
1084 }
1085 Some('\"') => {
1086 if self.dialect.supports_triple_quoted_string() {
1087 return self
1088 .tokenize_single_or_triple_quoted_string::<fn(String) -> Token>(
1089 chars,
1090 '"',
1091 false,
1092 Token::DoubleQuotedByteStringLiteral,
1093 Token::TripleDoubleQuotedByteStringLiteral,
1094 );
1095 }
1096 let s = self.tokenize_single_quoted_string(chars, '\"', false)?;
1097 Ok(Some(Token::DoubleQuotedByteStringLiteral(s)))
1098 }
1099 _ => {
1100 let s = self.tokenize_word(b, chars);
1102 Ok(Some(Token::make_word(&s, None)))
1103 }
1104 }
1105 }
1106 b @ 'R' | b @ 'r' if (self.dialect.is::<BigQueryDialect>() || self.dialect.is::<GenericDialect>())dialect_of!(self is BigQueryDialect | GenericDialect) => {
1108 chars.next(); match chars.peek() {
1110 Some('\'') => self
1111 .tokenize_single_or_triple_quoted_string::<fn(String) -> Token>(
1112 chars,
1113 '\'',
1114 false,
1115 Token::SingleQuotedRawStringLiteral,
1116 Token::TripleSingleQuotedRawStringLiteral,
1117 ),
1118 Some('\"') => self
1119 .tokenize_single_or_triple_quoted_string::<fn(String) -> Token>(
1120 chars,
1121 '"',
1122 false,
1123 Token::DoubleQuotedRawStringLiteral,
1124 Token::TripleDoubleQuotedRawStringLiteral,
1125 ),
1126 _ => {
1127 let s = self.tokenize_word(b, chars);
1129 Ok(Some(Token::make_word(&s, None)))
1130 }
1131 }
1132 }
1133 n @ 'N' | n @ 'n' => {
1135 chars.next(); match chars.peek() {
1137 Some('\'') => {
1138 let backslash_escape =
1140 self.dialect.supports_string_literal_backslash_escape();
1141 let s =
1142 self.tokenize_single_quoted_string(chars, '\'', backslash_escape)?;
1143 Ok(Some(Token::NationalStringLiteral(s)))
1144 }
1145 Some(&q @ 'q') | Some(&q @ 'Q')
1146 if self.dialect.supports_quote_delimited_string() =>
1147 {
1148 chars.next(); if let Some('\'') = chars.peek() {
1150 self.tokenize_quote_delimited_string(chars, &[n, q])
1151 .map(|s| Some(Token::NationalQuoteDelimitedStringLiteral(s)))
1152 } else {
1153 let s = self.tokenize_word(String::from_iter([n, q]), chars);
1154 Ok(Some(Token::make_word(&s, None)))
1155 }
1156 }
1157 _ => {
1158 let s = self.tokenize_word(n, chars);
1160 Ok(Some(Token::make_word(&s, None)))
1161 }
1162 }
1163 }
1164 q @ 'Q' | q @ 'q' if self.dialect.supports_quote_delimited_string() => {
1165 chars.next(); if let Some('\'') = chars.peek() {
1167 self.tokenize_quote_delimited_string(chars, &[q])
1168 .map(|s| Some(Token::QuoteDelimitedStringLiteral(s)))
1169 } else {
1170 let s = self.tokenize_word(q, chars);
1171 Ok(Some(Token::make_word(&s, None)))
1172 }
1173 }
1174 x @ 'e' | x @ 'E' if self.dialect.supports_string_escape_constant() => {
1176 let starting_loc = chars.location();
1177 chars.next(); match chars.peek() {
1179 Some('\'') => {
1180 let s =
1181 self.tokenize_escaped_single_quoted_string(starting_loc, chars)?;
1182 Ok(Some(Token::EscapedStringLiteral(s)))
1183 }
1184 _ => {
1185 let s = self.tokenize_word(x, chars);
1187 Ok(Some(Token::make_word(&s, None)))
1188 }
1189 }
1190 }
1191 x @ 'u' | x @ 'U' if self.dialect.supports_unicode_string_literal() => {
1193 chars.next(); if chars.peek() == Some(&'&') {
1195 let mut chars_clone = chars.peekable.clone();
1197 chars_clone.next(); if chars_clone.peek() == Some(&'\'') {
1199 chars.next(); let s = unescape_unicode_single_quoted_string(chars)?;
1201 return Ok(Some(Token::UnicodeStringLiteral(s)));
1202 }
1203 }
1204 let s = self.tokenize_word(x, chars);
1206 Ok(Some(Token::make_word(&s, None)))
1207 }
1208 x @ 'x' | x @ 'X' => {
1211 chars.next(); match chars.peek() {
1213 Some('\'') => {
1214 let s = self.tokenize_single_quoted_string(chars, '\'', true)?;
1216 Ok(Some(Token::HexStringLiteral(s)))
1217 }
1218 _ => {
1219 let s = self.tokenize_word(x, chars);
1221 Ok(Some(Token::make_word(&s, None)))
1222 }
1223 }
1224 }
1225 '\'' => {
1227 if self.dialect.supports_triple_quoted_string() {
1228 return self
1229 .tokenize_single_or_triple_quoted_string::<fn(String) -> Token>(
1230 chars,
1231 '\'',
1232 self.dialect.supports_string_literal_backslash_escape(),
1233 Token::SingleQuotedString,
1234 Token::TripleSingleQuotedString,
1235 );
1236 }
1237 let s = self.tokenize_single_quoted_string(
1238 chars,
1239 '\'',
1240 self.dialect.supports_string_literal_backslash_escape(),
1241 )?;
1242
1243 Ok(Some(Token::SingleQuotedString(s)))
1244 }
1245 '\"' if !self.dialect.is_delimited_identifier_start(ch)
1247 && !self.dialect.is_identifier_start(ch) =>
1248 {
1249 if self.dialect.supports_triple_quoted_string() {
1250 return self
1251 .tokenize_single_or_triple_quoted_string::<fn(String) -> Token>(
1252 chars,
1253 '"',
1254 self.dialect.supports_string_literal_backslash_escape(),
1255 Token::DoubleQuotedString,
1256 Token::TripleDoubleQuotedString,
1257 );
1258 }
1259 let s = self.tokenize_single_quoted_string(
1260 chars,
1261 '"',
1262 self.dialect.supports_string_literal_backslash_escape(),
1263 )?;
1264
1265 Ok(Some(Token::DoubleQuotedString(s)))
1266 }
1267 quote_start if self.dialect.is_delimited_identifier_start(ch) => {
1269 let word = self.tokenize_quoted_identifier(quote_start, chars)?;
1270 Ok(Some(Token::make_word(&word, Some(quote_start))))
1271 }
1272 quote_start
1274 if self
1275 .dialect
1276 .is_nested_delimited_identifier_start(quote_start)
1277 && self
1278 .dialect
1279 .peek_nested_delimited_identifier_quotes(chars.peekable.clone())
1280 .is_some() =>
1281 {
1282 let Some((quote_start, nested_quote_start)) = self
1283 .dialect
1284 .peek_nested_delimited_identifier_quotes(chars.peekable.clone())
1285 else {
1286 return self.tokenizer_error(
1287 chars.location(),
1288 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Expected nested delimiter \'{0}\' before EOF.",
quote_start))
})format!("Expected nested delimiter '{quote_start}' before EOF."),
1289 );
1290 };
1291
1292 let Some(nested_quote_start) = nested_quote_start else {
1293 let word = self.tokenize_quoted_identifier(quote_start, chars)?;
1294 return Ok(Some(Token::make_word(&word, Some(quote_start))));
1295 };
1296
1297 let mut word = ::alloc::vec::Vec::new()vec![];
1298 let quote_end = Word::matching_end_quote(quote_start);
1299 let nested_quote_end = Word::matching_end_quote(nested_quote_start);
1300 let error_loc = chars.location();
1301
1302 chars.next(); peeking_take_while(chars, |ch| ch.is_whitespace());
1304 if chars.peek() != Some(&nested_quote_start) {
1305 return self.tokenizer_error(
1306 error_loc,
1307 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Expected nested delimiter \'{0}\' before EOF.",
nested_quote_start))
})format!("Expected nested delimiter '{nested_quote_start}' before EOF."),
1308 );
1309 }
1310 word.push(nested_quote_start.into());
1311 word.push(self.tokenize_quoted_identifier(nested_quote_end, chars)?);
1312 word.push(nested_quote_end.into());
1313 peeking_take_while(chars, |ch| ch.is_whitespace());
1314 if chars.peek() != Some("e_end) {
1315 return self.tokenizer_error(
1316 error_loc,
1317 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Expected close delimiter \'{0}\' before EOF.",
quote_end))
})format!("Expected close delimiter '{quote_end}' before EOF."),
1318 );
1319 }
1320 chars.next(); Ok(Some(Token::make_word(&word.concat(), Some(quote_start))))
1323 }
1324 '0'..='9' | '.' => {
1326 if ch == '.' && chars.peekable.clone().nth(1) == Some('_') {
1331 if let Some(Token::Word(_)) = prev_token {
1332 chars.next();
1333 return Ok(Some(Token::Period));
1334 }
1335
1336 return self.tokenizer_error(
1337 chars.location(),
1338 "Unexpected character '_'".to_string(),
1339 );
1340 }
1341
1342 let is_number_separator = |ch: char, next_char: Option<char>| {
1345 self.dialect.supports_numeric_literal_underscores()
1346 && ch == '_'
1347 && next_char.is_some_and(|next_ch| next_ch.is_ascii_hexdigit())
1348 };
1349
1350 let mut s = peeking_next_take_while(chars, |ch, next_ch| {
1351 ch.is_ascii_digit() || is_number_separator(ch, next_ch)
1352 });
1353
1354 if s == "0" && chars.peek() == Some(&'x') {
1356 chars.next();
1357 let s2 = peeking_next_take_while(chars, |ch, next_ch| {
1358 ch.is_ascii_hexdigit() || is_number_separator(ch, next_ch)
1359 });
1360 return Ok(Some(Token::HexStringLiteral(s2)));
1361 }
1362
1363 if let Some('.') = chars.peek() {
1365 s.push('.');
1366 chars.next();
1367 }
1368
1369 if s == "." && self.dialect.supports_numeric_prefix() {
1375 if let Some(Token::Word(_)) = prev_token {
1376 return Ok(Some(Token::Period));
1377 }
1378 }
1379
1380 s += &peeking_next_take_while(chars, |ch, next_ch| {
1382 ch.is_ascii_digit() || is_number_separator(ch, next_ch)
1383 });
1384
1385 if s == "." {
1387 return Ok(Some(Token::Period));
1388 }
1389
1390 let mut exponent_part = String::new();
1392 if chars.peek() == Some(&'e') || chars.peek() == Some(&'E') {
1393 let mut char_clone = chars.peekable.clone();
1394 exponent_part.push(char_clone.next().unwrap());
1395
1396 match char_clone.peek() {
1398 Some(&c) if #[allow(non_exhaustive_omitted_patterns)] match c {
'+' | '-' => true,
_ => false,
}matches!(c, '+' | '-') => {
1399 exponent_part.push(c);
1400 char_clone.next();
1401 }
1402 _ => (),
1403 }
1404
1405 match char_clone.peek() {
1406 Some(&c) if c.is_ascii_digit() => {
1408 for _ in 0..exponent_part.len() {
1409 chars.next();
1410 }
1411 exponent_part +=
1412 &peeking_take_while(chars, |ch| ch.is_ascii_digit());
1413 s += exponent_part.as_str();
1414 }
1415 _ => (),
1417 }
1418 }
1419
1420 if self.dialect.supports_numeric_prefix() {
1424 if exponent_part.is_empty() {
1425 let word =
1428 peeking_take_while(chars, |ch| self.dialect.is_identifier_part(ch));
1429
1430 if !word.is_empty() {
1431 s += word.as_str();
1432 return Ok(Some(Token::make_word(s.as_str(), None)));
1433 }
1434 } else if prev_token == Some(&Token::Period) {
1435 return Ok(Some(Token::make_word(s.as_str(), None)));
1438 }
1439 }
1440
1441 let long = if chars.peek() == Some(&'L') {
1442 chars.next();
1443 true
1444 } else {
1445 false
1446 };
1447 Ok(Some(Token::Number(s, long)))
1448 }
1449 '(' => self.consume_and_return(chars, Token::LParen),
1451 ')' => self.consume_and_return(chars, Token::RParen),
1452 ',' => self.consume_and_return(chars, Token::Comma),
1453 '-' => {
1455 chars.next(); match chars.peek() {
1458 Some('-') => {
1459 let mut is_comment = true;
1460 if self.dialect.requires_single_line_comment_whitespace() {
1461 is_comment = chars
1462 .peekable
1463 .clone()
1464 .nth(1)
1465 .is_some_and(char::is_whitespace);
1466 }
1467
1468 if is_comment {
1469 chars.next(); let comment = self.tokenize_single_line_comment(chars);
1471 return Ok(Some(Token::Whitespace(
1472 Whitespace::SingleLineComment {
1473 prefix: "--".to_owned(),
1474 comment,
1475 },
1476 )));
1477 }
1478
1479 self.start_binop(chars, "-", Token::Minus)
1480 }
1481 Some('>') => {
1482 chars.next();
1483 match chars.peek() {
1484 Some('>') => self.consume_for_binop(chars, "->>", Token::LongArrow),
1485 _ => self.start_binop(chars, "->", Token::Arrow),
1486 }
1487 }
1488 _ => self.start_binop(chars, "-", Token::Minus),
1490 }
1491 }
1492 '/' => {
1493 chars.next(); match chars.peek() {
1495 Some('*') => {
1496 chars.next(); self.tokenize_multiline_comment(chars)
1498 }
1499 Some('/') if (self.dialect.is::<SnowflakeDialect>())dialect_of!(self is SnowflakeDialect) => {
1500 chars.next(); let comment = self.tokenize_single_line_comment(chars);
1502 Ok(Some(Token::Whitespace(Whitespace::SingleLineComment {
1503 prefix: "//".to_owned(),
1504 comment,
1505 })))
1506 }
1507 Some('/') if (self.dialect.is::<DuckDbDialect>() || self.dialect.is::<GenericDialect>())dialect_of!(self is DuckDbDialect | GenericDialect) => {
1508 self.consume_and_return(chars, Token::DuckIntDiv)
1509 }
1510 _ => Ok(Some(Token::Div)),
1512 }
1513 }
1514 '+' => self.consume_and_return(chars, Token::Plus),
1515 '*' => self.consume_and_return(chars, Token::Mul),
1516 '%' => {
1517 chars.next(); match chars.peek() {
1519 Some(s) if s.is_whitespace() => Ok(Some(Token::Mod)),
1520 Some(sch) if self.dialect.is_identifier_start('%') => {
1521 self.tokenize_identifier_or_keyword([ch, *sch], chars)
1522 }
1523 _ => self.start_binop(chars, "%", Token::Mod),
1524 }
1525 }
1526 '|' => {
1527 chars.next(); match chars.peek() {
1529 Some('/') => self.consume_for_binop(chars, "|/", Token::PGSquareRoot),
1530 Some('|') => {
1531 chars.next(); match chars.peek() {
1533 Some('/') => {
1534 self.consume_for_binop(chars, "||/", Token::PGCubeRoot)
1535 }
1536 _ => self.start_binop(chars, "||", Token::StringConcat),
1537 }
1538 }
1539 Some('&') if self.dialect.supports_geometric_types() => {
1540 chars.next(); match chars.peek() {
1542 Some('>') => self.consume_for_binop(
1543 chars,
1544 "|&>",
1545 Token::VerticalBarAmpersandRightAngleBracket,
1546 ),
1547 _ => self.start_binop_opt(chars, "|&", None),
1548 }
1549 }
1550 Some('>') if self.dialect.supports_geometric_types() => {
1551 chars.next(); match chars.peek() {
1553 Some('>') => self.consume_for_binop(
1554 chars,
1555 "|>>",
1556 Token::VerticalBarShiftRight,
1557 ),
1558 _ => self.start_binop_opt(chars, "|>", None),
1559 }
1560 }
1561 Some('>') if self.dialect.supports_pipe_operator() => {
1562 self.consume_for_binop(chars, "|>", Token::VerticalBarRightAngleBracket)
1563 }
1564 _ => self.start_binop(chars, "|", Token::Pipe),
1566 }
1567 }
1568 '=' => {
1569 chars.next(); match chars.peek() {
1571 Some('>') => self.consume_and_return(chars, Token::RArrow),
1572 Some('=') => self.consume_and_return(chars, Token::DoubleEq),
1573 _ => Ok(Some(Token::Eq)),
1574 }
1575 }
1576 '!' => {
1577 chars.next(); match chars.peek() {
1579 Some('=') => self.consume_and_return(chars, Token::Neq),
1580 Some('!') => self.consume_and_return(chars, Token::DoubleExclamationMark),
1581 Some('~') => {
1582 chars.next();
1583 match chars.peek() {
1584 Some('*') => self
1585 .consume_and_return(chars, Token::ExclamationMarkTildeAsterisk),
1586 Some('~') => {
1587 chars.next();
1588 match chars.peek() {
1589 Some('*') => self.consume_and_return(
1590 chars,
1591 Token::ExclamationMarkDoubleTildeAsterisk,
1592 ),
1593 _ => Ok(Some(Token::ExclamationMarkDoubleTilde)),
1594 }
1595 }
1596 _ => Ok(Some(Token::ExclamationMarkTilde)),
1597 }
1598 }
1599 _ => Ok(Some(Token::ExclamationMark)),
1600 }
1601 }
1602 '<' => {
1603 chars.next(); match chars.peek() {
1605 Some('=') => {
1606 chars.next();
1607 match chars.peek() {
1608 Some('>') => self.consume_for_binop(chars, "<=>", Token::Spaceship),
1609 _ => self.start_binop(chars, "<=", Token::LtEq),
1610 }
1611 }
1612 Some('|') if self.dialect.supports_geometric_types() => {
1613 self.consume_for_binop(chars, "<<|", Token::ShiftLeftVerticalBar)
1614 }
1615 Some('>') => self.consume_for_binop(chars, "<>", Token::Neq),
1616 Some('<') if self.dialect.supports_geometric_types() => {
1617 chars.next(); match chars.peek() {
1619 Some('|') => self.consume_for_binop(
1620 chars,
1621 "<<|",
1622 Token::ShiftLeftVerticalBar,
1623 ),
1624 _ => self.start_binop(chars, "<<", Token::ShiftLeft),
1625 }
1626 }
1627 Some('<') => self.consume_for_binop(chars, "<<", Token::ShiftLeft),
1628 Some('-') if self.dialect.supports_geometric_types() => {
1629 chars.next(); match chars.peek() {
1631 Some('>') => {
1632 self.consume_for_binop(chars, "<->", Token::TwoWayArrow)
1633 }
1634 _ => self.start_binop_opt(chars, "<-", None),
1635 }
1636 }
1637 Some('^') if self.dialect.supports_geometric_types() => {
1638 self.consume_for_binop(chars, "<^", Token::LeftAngleBracketCaret)
1639 }
1640 Some('@') => self.consume_for_binop(chars, "<@", Token::ArrowAt),
1641 _ => self.start_binop(chars, "<", Token::Lt),
1642 }
1643 }
1644 '>' => {
1645 chars.next(); match chars.peek() {
1647 Some('=') => self.consume_for_binop(chars, ">=", Token::GtEq),
1648 Some('>') => self.consume_for_binop(chars, ">>", Token::ShiftRight),
1649 Some('^') if self.dialect.supports_geometric_types() => {
1650 self.consume_for_binop(chars, ">^", Token::RightAngleBracketCaret)
1651 }
1652 _ => self.start_binop(chars, ">", Token::Gt),
1653 }
1654 }
1655 ':' => {
1656 chars.next();
1657 match chars.peek() {
1658 Some(':') => self.consume_and_return(chars, Token::DoubleColon),
1659 Some('=') => self.consume_and_return(chars, Token::Assignment),
1660 _ => Ok(Some(Token::Colon)),
1661 }
1662 }
1663 ';' => self.consume_and_return(chars, Token::SemiColon),
1664 '\\' => self.consume_and_return(chars, Token::Backslash),
1665 '[' => self.consume_and_return(chars, Token::LBracket),
1666 ']' => self.consume_and_return(chars, Token::RBracket),
1667 '&' => {
1668 chars.next(); match chars.peek() {
1670 Some('>') if self.dialect.supports_geometric_types() => {
1671 chars.next();
1672 self.consume_and_return(chars, Token::AmpersandRightAngleBracket)
1673 }
1674 Some('<') if self.dialect.supports_geometric_types() => {
1675 chars.next(); match chars.peek() {
1677 Some('|') => self.consume_and_return(
1678 chars,
1679 Token::AmpersandLeftAngleBracketVerticalBar,
1680 ),
1681 _ => {
1682 self.start_binop(chars, "&<", Token::AmpersandLeftAngleBracket)
1683 }
1684 }
1685 }
1686 Some('&') => {
1687 chars.next(); self.start_binop(chars, "&&", Token::Overlap)
1689 }
1690 _ => self.start_binop(chars, "&", Token::Ampersand),
1692 }
1693 }
1694 '^' => {
1695 chars.next(); match chars.peek() {
1697 Some('@') => self.consume_and_return(chars, Token::CaretAt),
1698 _ => Ok(Some(Token::Caret)),
1699 }
1700 }
1701 '{' => self.consume_and_return(chars, Token::LBrace),
1702 '}' => self.consume_and_return(chars, Token::RBrace),
1703 '#' if (self.dialect.is::<SnowflakeDialect>() || self.dialect.is::<BigQueryDialect>()
|| self.dialect.is::<MySqlDialect>() ||
self.dialect.is::<HiveDialect>())dialect_of!(self is SnowflakeDialect | BigQueryDialect | MySqlDialect | HiveDialect) =>
1704 {
1705 chars.next(); let comment = self.tokenize_single_line_comment(chars);
1707 Ok(Some(Token::Whitespace(Whitespace::SingleLineComment {
1708 prefix: "#".to_owned(),
1709 comment,
1710 })))
1711 }
1712 '~' => {
1713 chars.next(); match chars.peek() {
1715 Some('*') => self.consume_for_binop(chars, "~*", Token::TildeAsterisk),
1716 Some('=') if self.dialect.supports_geometric_types() => {
1717 self.consume_for_binop(chars, "~=", Token::TildeEqual)
1718 }
1719 Some('~') => {
1720 chars.next();
1721 match chars.peek() {
1722 Some('*') => {
1723 self.consume_for_binop(chars, "~~*", Token::DoubleTildeAsterisk)
1724 }
1725 _ => self.start_binop(chars, "~~", Token::DoubleTilde),
1726 }
1727 }
1728 _ => self.start_binop(chars, "~", Token::Tilde),
1729 }
1730 }
1731 '#' => {
1732 chars.next();
1733 match chars.peek() {
1734 Some('-') => self.consume_for_binop(chars, "#-", Token::HashMinus),
1735 Some('>') => {
1736 chars.next();
1737 match chars.peek() {
1738 Some('>') => {
1739 self.consume_for_binop(chars, "#>>", Token::HashLongArrow)
1740 }
1741 _ => self.start_binop(chars, "#>", Token::HashArrow),
1742 }
1743 }
1744 Some(' ') => Ok(Some(Token::Sharp)),
1745 Some('#') if self.dialect.supports_geometric_types() => {
1746 self.consume_for_binop(chars, "##", Token::DoubleSharp)
1747 }
1748 Some(sch) if self.dialect.is_identifier_start('#') => {
1749 self.tokenize_identifier_or_keyword([ch, *sch], chars)
1750 }
1751 _ => self.start_binop(chars, "#", Token::Sharp),
1752 }
1753 }
1754 '@' => {
1755 chars.next();
1756 match chars.peek() {
1757 Some('@') if self.dialect.supports_geometric_types() => {
1758 self.consume_and_return(chars, Token::AtAt)
1759 }
1760 Some('-') if self.dialect.supports_geometric_types() => {
1761 chars.next();
1762 match chars.peek() {
1763 Some('@') => self.consume_and_return(chars, Token::AtDashAt),
1764 _ => self.start_binop_opt(chars, "@-", None),
1765 }
1766 }
1767 Some('>') => self.consume_and_return(chars, Token::AtArrow),
1768 Some('?') => self.consume_and_return(chars, Token::AtQuestion),
1769 Some('@') => {
1770 chars.next();
1771 match chars.peek() {
1772 Some(' ') => Ok(Some(Token::AtAt)),
1773 Some(tch) if self.dialect.is_identifier_start('@') => {
1774 self.tokenize_identifier_or_keyword([ch, '@', *tch], chars)
1775 }
1776 _ => Ok(Some(Token::AtAt)),
1777 }
1778 }
1779 Some(' ') => Ok(Some(Token::AtSign)),
1780 Some('\'') => Ok(Some(Token::AtSign)),
1790 Some('\"') => Ok(Some(Token::AtSign)),
1791 Some('`') => Ok(Some(Token::AtSign)),
1792 Some(sch) if self.dialect.is_identifier_start('@') => {
1793 self.tokenize_identifier_or_keyword([ch, *sch], chars)
1794 }
1795 _ => Ok(Some(Token::AtSign)),
1796 }
1797 }
1798 '?' if self.dialect.supports_geometric_types() => {
1800 chars.next(); match chars.peek() {
1802 Some('|') => {
1803 chars.next();
1804 match chars.peek() {
1805 Some('|') => self.consume_and_return(
1806 chars,
1807 Token::QuestionMarkDoubleVerticalBar,
1808 ),
1809 _ => Ok(Some(Token::QuestionPipe)),
1810 }
1811 }
1812
1813 Some('&') => self.consume_and_return(chars, Token::QuestionAnd),
1814 Some('-') => {
1815 chars.next(); match chars.peek() {
1817 Some('|') => self
1818 .consume_and_return(chars, Token::QuestionMarkDashVerticalBar),
1819 _ => Ok(Some(Token::QuestionMarkDash)),
1820 }
1821 }
1822 Some('#') => self.consume_and_return(chars, Token::QuestionMarkSharp),
1823 _ => Ok(Some(Token::Question)),
1824 }
1825 }
1826 '?' => {
1827 chars.next();
1828 let s = peeking_take_while(chars, |ch| ch.is_numeric());
1829 Ok(Some(Token::Placeholder(::alloc::__export::must_use({ ::alloc::fmt::format(format_args!("?{0}", s)) })format!("?{s}"))))
1830 }
1831
1832 ch if self.dialect.is_identifier_start(ch) => {
1834 self.tokenize_identifier_or_keyword([ch], chars)
1835 }
1836 '$' => Ok(Some(self.tokenize_dollar_preceded_value(chars)?)),
1837
1838 ch if ch.is_whitespace() => {
1840 self.consume_and_return(chars, Token::Whitespace(Whitespace::Space))
1841 }
1842 other => self.consume_and_return(chars, Token::Char(other)),
1843 },
1844 None => Ok(None),
1845 }
1846 }
1847
1848 fn consume_for_binop(
1850 &self,
1851 chars: &mut State,
1852 prefix: &str,
1853 default: Token,
1854 ) -> Result<Option<Token>, TokenizerError> {
1855 chars.next(); self.start_binop_opt(chars, prefix, Some(default))
1857 }
1858
1859 fn start_binop(
1861 &self,
1862 chars: &mut State,
1863 prefix: &str,
1864 default: Token,
1865 ) -> Result<Option<Token>, TokenizerError> {
1866 self.start_binop_opt(chars, prefix, Some(default))
1867 }
1868
1869 fn start_binop_opt(
1871 &self,
1872 chars: &mut State,
1873 prefix: &str,
1874 default: Option<Token>,
1875 ) -> Result<Option<Token>, TokenizerError> {
1876 let mut custom = None;
1877 while let Some(&ch) = chars.peek() {
1878 if !self.dialect.is_custom_operator_part(ch) {
1879 break;
1880 }
1881
1882 custom.get_or_insert_with(|| prefix.to_string()).push(ch);
1883 chars.next();
1884 }
1885 match (custom, default) {
1886 (Some(custom), _) => Ok(Token::CustomBinaryOperator(custom).into()),
1887 (None, Some(tok)) => Ok(Some(tok)),
1888 (None, None) => self.tokenizer_error(
1889 chars.location(),
1890 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Expected a valid binary operator after \'{0}\'",
prefix))
})format!("Expected a valid binary operator after '{prefix}'"),
1891 ),
1892 }
1893 }
1894
1895 fn tokenize_dollar_preceded_value(&self, chars: &mut State) -> Result<Token, TokenizerError> {
1897 let mut s = String::new();
1898 let mut value = String::new();
1899
1900 chars.next();
1901
1902 if #[allow(non_exhaustive_omitted_patterns)] match chars.peek() {
Some('$') => true,
_ => false,
}matches!(chars.peek(), Some('$')) && !self.dialect.supports_dollar_placeholder() {
1904 chars.next();
1905
1906 let mut is_terminated = false;
1907 let mut prev: Option<char> = None;
1908
1909 while let Some(&ch) = chars.peek() {
1910 if prev == Some('$') {
1911 if ch == '$' {
1912 chars.next();
1913 is_terminated = true;
1914 break;
1915 } else {
1916 s.push('$');
1917 s.push(ch);
1918 }
1919 } else if ch != '$' {
1920 s.push(ch);
1921 }
1922
1923 prev = Some(ch);
1924 chars.next();
1925 }
1926
1927 return if chars.peek().is_none() && !is_terminated {
1928 self.tokenizer_error(chars.location(), "Unterminated dollar-quoted string")
1929 } else {
1930 Ok(Token::DollarQuotedString(DollarQuotedString {
1931 value: s,
1932 tag: None,
1933 }))
1934 };
1935 } else {
1936 value.push_str(&peeking_take_while(chars, |ch| {
1937 ch.is_alphanumeric()
1938 || ch == '_'
1939 || #[allow(non_exhaustive_omitted_patterns)] match ch {
'$' if self.dialect.supports_dollar_placeholder() => true,
_ => false,
}matches!(ch, '$' if self.dialect.supports_dollar_placeholder())
1941 }));
1942
1943 if #[allow(non_exhaustive_omitted_patterns)] match chars.peek() {
Some('$') => true,
_ => false,
}matches!(chars.peek(), Some('$')) && !self.dialect.supports_dollar_placeholder() {
1945 chars.next();
1946
1947 let mut temp = String::new();
1948 let end_delimiter = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("${0}$", value))
})format!("${value}$");
1949
1950 loop {
1951 match chars.next() {
1952 Some(ch) => {
1953 temp.push(ch);
1954
1955 if temp.ends_with(&end_delimiter) {
1956 if let Some(temp) = temp.strip_suffix(&end_delimiter) {
1957 s.push_str(temp);
1958 }
1959 break;
1960 }
1961 }
1962 None => {
1963 if temp.ends_with(&end_delimiter) {
1964 if let Some(temp) = temp.strip_suffix(&end_delimiter) {
1965 s.push_str(temp);
1966 }
1967 break;
1968 }
1969
1970 return self.tokenizer_error(
1971 chars.location(),
1972 "Unterminated dollar-quoted, expected $",
1973 );
1974 }
1975 }
1976 }
1977 } else {
1978 return Ok(Token::Placeholder(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("${0}", value))
})format!("${value}")));
1979 }
1980 }
1981
1982 Ok(Token::DollarQuotedString(DollarQuotedString {
1983 value: s,
1984 tag: if value.is_empty() { None } else { Some(value) },
1985 }))
1986 }
1987
1988 fn tokenizer_error<R>(
1989 &self,
1990 loc: Location,
1991 message: impl Into<String>,
1992 ) -> Result<R, TokenizerError> {
1993 Err(TokenizerError {
1994 message: message.into(),
1995 location: loc,
1996 })
1997 }
1998
1999 fn tokenize_single_line_comment(&self, chars: &mut State) -> String {
2001 let mut comment = peeking_take_while(chars, |ch| match ch {
2002 '\n' => false, '\r' if (self.dialect.is::<PostgreSqlDialect>())dialect_of!(self is PostgreSqlDialect) => false, _ => true, });
2006
2007 if let Some(ch) = chars.next() {
2008 if !(ch == '\n' || ch == '\r') {
::core::panicking::panic("assertion failed: ch == \'\\n\' || ch == \'\\r\'")
};assert!(ch == '\n' || ch == '\r');
2009 comment.push(ch);
2010 }
2011
2012 comment
2013 }
2014
2015 fn tokenize_word(&self, first_chars: impl Into<String>, chars: &mut State) -> String {
2017 let mut s = first_chars.into();
2018 s.push_str(&peeking_take_while(chars, |ch| {
2019 self.dialect.is_identifier_part(ch)
2020 }));
2021 s
2022 }
2023
2024 fn tokenize_quoted_identifier(
2026 &self,
2027 quote_start: char,
2028 chars: &mut State,
2029 ) -> Result<String, TokenizerError> {
2030 let error_loc = chars.location();
2031 chars.next(); let quote_end = Word::matching_end_quote(quote_start);
2033 let (s, last_char) = self.parse_quoted_ident(chars, quote_end);
2034
2035 if last_char == Some(quote_end) {
2036 Ok(s)
2037 } else {
2038 self.tokenizer_error(
2039 error_loc,
2040 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Expected close delimiter \'{0}\' before EOF.",
quote_end))
})format!("Expected close delimiter '{quote_end}' before EOF."),
2041 )
2042 }
2043 }
2044
2045 fn tokenize_escaped_single_quoted_string(
2047 &self,
2048 starting_loc: Location,
2049 chars: &mut State,
2050 ) -> Result<String, TokenizerError> {
2051 if let Some(s) = unescape_single_quoted_string(chars) {
2052 return Ok(s);
2053 }
2054
2055 self.tokenizer_error(starting_loc, "Unterminated encoded string literal")
2056 }
2057
2058 fn tokenize_single_or_triple_quoted_string<F>(
2061 &self,
2062 chars: &mut State,
2063 quote_style: char,
2064 backslash_escape: bool,
2065 single_quote_token: F,
2066 triple_quote_token: F,
2067 ) -> Result<Option<Token>, TokenizerError>
2068 where
2069 F: Fn(String) -> Token,
2070 {
2071 let error_loc = chars.location();
2072
2073 let mut num_opening_quotes = 0u8;
2074 for _ in 0..3 {
2075 if Some("e_style) == chars.peek() {
2076 chars.next(); num_opening_quotes += 1;
2078 } else {
2079 break;
2080 }
2081 }
2082
2083 let (token_fn, num_quote_chars) = match num_opening_quotes {
2084 1 => (single_quote_token, NumStringQuoteChars::One),
2085 2 => {
2086 return Ok(Some(single_quote_token("".into())));
2088 }
2089 3 => {
2090 let Some(num_quote_chars) = NonZeroU8::new(3) else {
2091 return self.tokenizer_error(error_loc, "invalid number of opening quotes");
2092 };
2093 (
2094 triple_quote_token,
2095 NumStringQuoteChars::Many(num_quote_chars),
2096 )
2097 }
2098 _ => {
2099 return self.tokenizer_error(error_loc, "invalid string literal opening");
2100 }
2101 };
2102
2103 let settings = TokenizeQuotedStringSettings {
2104 quote_style,
2105 num_quote_chars,
2106 num_opening_quotes_to_consume: 0,
2107 backslash_escape,
2108 };
2109
2110 self.tokenize_quoted_string(chars, settings)
2111 .map(token_fn)
2112 .map(Some)
2113 }
2114
2115 fn tokenize_single_quoted_string(
2117 &self,
2118 chars: &mut State,
2119 quote_style: char,
2120 backslash_escape: bool,
2121 ) -> Result<String, TokenizerError> {
2122 self.tokenize_quoted_string(
2123 chars,
2124 TokenizeQuotedStringSettings {
2125 quote_style,
2126 num_quote_chars: NumStringQuoteChars::One,
2127 num_opening_quotes_to_consume: 1,
2128 backslash_escape,
2129 },
2130 )
2131 }
2132
2133 fn tokenize_quote_delimited_string(
2137 &self,
2138 chars: &mut State,
2139 literal_prefix: &[char],
2142 ) -> Result<QuoteDelimitedString, TokenizerError> {
2143 let literal_start_loc = chars.location();
2144 chars.next();
2145
2146 let start_quote_loc = chars.location();
2147 let (start_quote, end_quote) = match chars.next() {
2148 None | Some(' ') | Some('\t') | Some('\r') | Some('\n') => {
2149 return self.tokenizer_error(
2150 start_quote_loc,
2151 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Invalid space, tab, newline, or EOF after \'{0}\'\'",
String::from_iter(literal_prefix)))
})format!(
2152 "Invalid space, tab, newline, or EOF after '{}''",
2153 String::from_iter(literal_prefix)
2154 ),
2155 );
2156 }
2157 Some(c) => (
2158 c,
2159 match c {
2160 '[' => ']',
2161 '{' => '}',
2162 '<' => '>',
2163 '(' => ')',
2164 c => c,
2165 },
2166 ),
2167 };
2168
2169 let mut value = String::new();
2171 while let Some(ch) = chars.next() {
2172 if ch == end_quote {
2173 if let Some('\'') = chars.peek() {
2174 chars.next(); return Ok(QuoteDelimitedString {
2176 start_quote,
2177 value,
2178 end_quote,
2179 });
2180 }
2181 }
2182 value.push(ch);
2183 }
2184
2185 self.tokenizer_error(literal_start_loc, "Unterminated string literal")
2186 }
2187
2188 fn tokenize_quoted_string(
2190 &self,
2191 chars: &mut State,
2192 settings: TokenizeQuotedStringSettings,
2193 ) -> Result<String, TokenizerError> {
2194 let mut s = String::new();
2195 let error_loc = chars.location();
2196
2197 for _ in 0..settings.num_opening_quotes_to_consume {
2199 if Some(settings.quote_style) != chars.next() {
2200 return self.tokenizer_error(error_loc, "invalid string literal opening");
2201 }
2202 }
2203
2204 let mut num_consecutive_quotes = 0;
2205 while let Some(&ch) = chars.peek() {
2206 let pending_final_quote = match settings.num_quote_chars {
2207 NumStringQuoteChars::One => Some(NumStringQuoteChars::One),
2208 n @ NumStringQuoteChars::Many(count)
2209 if num_consecutive_quotes + 1 == count.get() =>
2210 {
2211 Some(n)
2212 }
2213 NumStringQuoteChars::Many(_) => None,
2214 };
2215
2216 match ch {
2217 char if char == settings.quote_style && pending_final_quote.is_some() => {
2218 chars.next(); if let Some(NumStringQuoteChars::Many(count)) = pending_final_quote {
2221 let mut buf = s.chars();
2226 for _ in 1..count.get() {
2227 buf.next_back();
2228 }
2229 return Ok(buf.as_str().to_string());
2230 } else if chars
2231 .peek()
2232 .map(|c| *c == settings.quote_style)
2233 .unwrap_or(false)
2234 {
2235 s.push(ch);
2236 if !self.unescape {
2237 s.push(ch);
2239 }
2240 chars.next();
2241 } else {
2242 return Ok(s);
2243 }
2244 }
2245 '\\' if settings.backslash_escape => {
2246 chars.next();
2248
2249 num_consecutive_quotes = 0;
2250
2251 if let Some(next) = chars.peek() {
2252 if !self.unescape
2253 || (self.dialect.ignores_wildcard_escapes()
2254 && (*next == '%' || *next == '_'))
2255 {
2256 s.push(ch);
2260 s.push(*next);
2261 chars.next(); } else {
2263 let n = match next {
2264 '0' => '\0',
2265 'a' => '\u{7}',
2266 'b' => '\u{8}',
2267 'f' => '\u{c}',
2268 'n' => '\n',
2269 'r' => '\r',
2270 't' => '\t',
2271 'Z' => '\u{1a}',
2272 _ => *next,
2273 };
2274 s.push(n);
2275 chars.next(); }
2277 }
2278 }
2279 ch => {
2280 chars.next(); if ch == settings.quote_style {
2283 num_consecutive_quotes += 1;
2284 } else {
2285 num_consecutive_quotes = 0;
2286 }
2287
2288 s.push(ch);
2289 }
2290 }
2291 }
2292 self.tokenizer_error(error_loc, "Unterminated string literal")
2293 }
2294
2295 fn tokenize_multiline_comment(
2296 &self,
2297 chars: &mut State,
2298 ) -> Result<Option<Token>, TokenizerError> {
2299 let mut s = String::new();
2300 let mut nested = 1;
2301 let supports_nested_comments = self.dialect.supports_nested_comments();
2302 loop {
2303 match chars.next() {
2304 Some('/') if #[allow(non_exhaustive_omitted_patterns)] match chars.peek() {
Some('*') => true,
_ => false,
}matches!(chars.peek(), Some('*')) && supports_nested_comments => {
2305 chars.next(); s.push('/');
2307 s.push('*');
2308 nested += 1;
2309 }
2310 Some('*') if #[allow(non_exhaustive_omitted_patterns)] match chars.peek() {
Some('/') => true,
_ => false,
}matches!(chars.peek(), Some('/')) => {
2311 chars.next(); nested -= 1;
2313 if nested == 0 {
2314 break Ok(Some(Token::Whitespace(Whitespace::MultiLineComment(s))));
2315 }
2316 s.push('*');
2317 s.push('/');
2318 }
2319 Some(ch) => {
2320 s.push(ch);
2321 }
2322 None => {
2323 break self.tokenizer_error(
2324 chars.location(),
2325 "Unexpected EOF while in a multi-line comment",
2326 );
2327 }
2328 }
2329 }
2330 }
2331
2332 fn parse_quoted_ident(&self, chars: &mut State, quote_end: char) -> (String, Option<char>) {
2333 let mut last_char = None;
2334 let mut s = String::new();
2335 while let Some(ch) = chars.next() {
2336 if ch == quote_end {
2337 if chars.peek() == Some("e_end) {
2338 chars.next();
2339 s.push(ch);
2340 if !self.unescape {
2341 s.push(ch);
2343 }
2344 } else {
2345 last_char = Some(quote_end);
2346 break;
2347 }
2348 } else {
2349 s.push(ch);
2350 }
2351 }
2352 (s, last_char)
2353 }
2354
2355 #[allow(clippy::unnecessary_wraps)]
2356 fn consume_and_return(
2357 &self,
2358 chars: &mut State,
2359 t: Token,
2360 ) -> Result<Option<Token>, TokenizerError> {
2361 chars.next();
2362 Ok(Some(t))
2363 }
2364}
2365
2366fn peeking_take_while(chars: &mut State, mut predicate: impl FnMut(char) -> bool) -> String {
2370 let mut s = String::new();
2371 while let Some(&ch) = chars.peek() {
2372 if predicate(ch) {
2373 chars.next(); s.push(ch);
2375 } else {
2376 break;
2377 }
2378 }
2379 s
2380}
2381
2382fn peeking_next_take_while(
2384 chars: &mut State,
2385 mut predicate: impl FnMut(char, Option<char>) -> bool,
2386) -> String {
2387 let mut s = String::new();
2388 while let Some(&ch) = chars.peek() {
2389 let next_char = chars.peekable.clone().nth(1);
2390 if predicate(ch, next_char) {
2391 chars.next(); s.push(ch);
2393 } else {
2394 break;
2395 }
2396 }
2397 s
2398}
2399
2400fn unescape_single_quoted_string(chars: &mut State<'_>) -> Option<String> {
2401 Unescape::new(chars).unescape()
2402}
2403
2404struct Unescape<'a: 'b, 'b> {
2405 chars: &'b mut State<'a>,
2406}
2407
2408impl<'a: 'b, 'b> Unescape<'a, 'b> {
2409 fn new(chars: &'b mut State<'a>) -> Self {
2410 Self { chars }
2411 }
2412 fn unescape(mut self) -> Option<String> {
2413 let mut unescaped = String::new();
2414
2415 self.chars.next();
2416
2417 while let Some(c) = self.chars.next() {
2418 if c == '\'' {
2419 if self.chars.peek().map(|c| *c == '\'').unwrap_or(false) {
2421 self.chars.next();
2422 unescaped.push('\'');
2423 continue;
2424 }
2425 return Some(unescaped);
2426 }
2427
2428 if c != '\\' {
2429 unescaped.push(c);
2430 continue;
2431 }
2432
2433 let c = match self.chars.next()? {
2434 'b' => '\u{0008}',
2435 'f' => '\u{000C}',
2436 'n' => '\n',
2437 'r' => '\r',
2438 't' => '\t',
2439 'u' => self.unescape_unicode_16()?,
2440 'U' => self.unescape_unicode_32()?,
2441 'x' => self.unescape_hex()?,
2442 c if c.is_digit(8) => self.unescape_octal(c)?,
2443 c => c,
2444 };
2445
2446 unescaped.push(Self::check_null(c)?);
2447 }
2448
2449 None
2450 }
2451
2452 #[inline]
2453 fn check_null(c: char) -> Option<char> {
2454 if c == '\0' {
2455 None
2456 } else {
2457 Some(c)
2458 }
2459 }
2460
2461 #[inline]
2462 fn byte_to_char<const RADIX: u32>(s: &str) -> Option<char> {
2463 match u32::from_str_radix(s, RADIX) {
2465 Err(_) => None,
2466 Ok(n) => {
2467 let n = n & 0xFF;
2468 if n <= 127 {
2469 char::from_u32(n)
2470 } else {
2471 None
2472 }
2473 }
2474 }
2475 }
2476
2477 fn unescape_hex(&mut self) -> Option<char> {
2479 let mut s = String::new();
2480
2481 for _ in 0..2 {
2482 match self.next_hex_digit() {
2483 Some(c) => s.push(c),
2484 None => break,
2485 }
2486 }
2487
2488 if s.is_empty() {
2489 return Some('x');
2490 }
2491
2492 Self::byte_to_char::<16>(&s)
2493 }
2494
2495 #[inline]
2496 fn next_hex_digit(&mut self) -> Option<char> {
2497 match self.chars.peek() {
2498 Some(c) if c.is_ascii_hexdigit() => self.chars.next(),
2499 _ => None,
2500 }
2501 }
2502
2503 fn unescape_octal(&mut self, c: char) -> Option<char> {
2505 let mut s = String::new();
2506
2507 s.push(c);
2508 for _ in 0..2 {
2509 match self.next_octal_digest() {
2510 Some(c) => s.push(c),
2511 None => break,
2512 }
2513 }
2514
2515 Self::byte_to_char::<8>(&s)
2516 }
2517
2518 #[inline]
2519 fn next_octal_digest(&mut self) -> Option<char> {
2520 match self.chars.peek() {
2521 Some(c) if c.is_digit(8) => self.chars.next(),
2522 _ => None,
2523 }
2524 }
2525
2526 fn unescape_unicode_16(&mut self) -> Option<char> {
2528 self.unescape_unicode::<4>()
2529 }
2530
2531 fn unescape_unicode_32(&mut self) -> Option<char> {
2533 self.unescape_unicode::<8>()
2534 }
2535
2536 fn unescape_unicode<const NUM: usize>(&mut self) -> Option<char> {
2537 let mut s = String::new();
2538 for _ in 0..NUM {
2539 s.push(self.chars.next()?);
2540 }
2541 match u32::from_str_radix(&s, 16) {
2542 Err(_) => None,
2543 Ok(n) => char::from_u32(n),
2544 }
2545 }
2546}
2547
2548fn unescape_unicode_single_quoted_string(chars: &mut State<'_>) -> Result<String, TokenizerError> {
2549 let mut unescaped = String::new();
2550 chars.next(); while let Some(c) = chars.next() {
2552 match c {
2553 '\'' => {
2554 if chars.peek() == Some(&'\'') {
2555 chars.next();
2556 unescaped.push('\'');
2557 } else {
2558 return Ok(unescaped);
2559 }
2560 }
2561 '\\' => match chars.peek() {
2562 Some('\\') => {
2563 chars.next();
2564 unescaped.push('\\');
2565 }
2566 Some('+') => {
2567 chars.next();
2568 unescaped.push(take_char_from_hex_digits(chars, 6)?);
2569 }
2570 _ => unescaped.push(take_char_from_hex_digits(chars, 4)?),
2571 },
2572 _ => {
2573 unescaped.push(c);
2574 }
2575 }
2576 }
2577 Err(TokenizerError {
2578 message: "Unterminated unicode encoded string literal".to_string(),
2579 location: chars.location(),
2580 })
2581}
2582
2583fn take_char_from_hex_digits(
2584 chars: &mut State<'_>,
2585 max_digits: usize,
2586) -> Result<char, TokenizerError> {
2587 let mut result = 0u32;
2588 for _ in 0..max_digits {
2589 let next_char = chars.next().ok_or_else(|| TokenizerError {
2590 message: "Unexpected EOF while parsing hex digit in escaped unicode string."
2591 .to_string(),
2592 location: chars.location(),
2593 })?;
2594 let digit = next_char.to_digit(16).ok_or_else(|| TokenizerError {
2595 message: ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Invalid hex digit in escaped unicode string: {0}",
next_char))
})format!("Invalid hex digit in escaped unicode string: {next_char}"),
2596 location: chars.location(),
2597 })?;
2598 result = result * 16 + digit;
2599 }
2600 char::from_u32(result).ok_or_else(|| TokenizerError {
2601 message: ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Invalid unicode character: {0:x}",
result))
})format!("Invalid unicode character: {result:x}"),
2602 location: chars.location(),
2603 })
2604}
2605
2606#[cfg(test)]
2607mod tests {
2608 use super::*;
2609 use crate::dialect::{
2610 BigQueryDialect, ClickHouseDialect, HiveDialect, MsSqlDialect, MySqlDialect, SQLiteDialect,
2611 };
2612 use crate::test_utils::{all_dialects_except, all_dialects_where};
2613 use core::fmt::Debug;
2614
2615 #[test]
2616 fn tokenizer_error_impl() {
2617 let err = TokenizerError {
2618 message: "test".into(),
2619 location: Location { line: 1, column: 1 },
2620 };
2621 {
2622 use core::error::Error;
2623 assert!(err.source().is_none());
2624 }
2625 assert_eq!(err.to_string(), "test at Line: 1, Column: 1");
2626 }
2627
2628 #[test]
2629 fn tokenize_select_1() {
2630 let sql = String::from("SELECT 1");
2631 let dialect = GenericDialect {};
2632 let tokens = Tokenizer::new(&dialect, &sql).tokenize().unwrap();
2633
2634 let expected = vec![
2635 Token::make_keyword("SELECT"),
2636 Token::Whitespace(Whitespace::Space),
2637 Token::Number(String::from("1"), false),
2638 ];
2639
2640 compare(expected, tokens);
2641 }
2642
2643 #[test]
2644 fn tokenize_select_float() {
2645 let sql = String::from("SELECT .1");
2646 let dialect = GenericDialect {};
2647 let tokens = Tokenizer::new(&dialect, &sql).tokenize().unwrap();
2648
2649 let expected = vec![
2650 Token::make_keyword("SELECT"),
2651 Token::Whitespace(Whitespace::Space),
2652 Token::Number(String::from(".1"), false),
2653 ];
2654
2655 compare(expected, tokens);
2656 }
2657
2658 #[test]
2659 fn tokenize_with_mapper() {
2660 let sql = String::from("SELECT ?");
2661 let dialect = GenericDialect {};
2662 let mut param_num = 1;
2663
2664 let mut tokens = vec![];
2665 Tokenizer::new(&dialect, &sql)
2666 .tokenize_with_location_into_buf_with_mapper(&mut tokens, |mut token_span| {
2667 token_span.token = match token_span.token {
2668 Token::Placeholder(n) => Token::Placeholder(if n == "?" {
2669 let ret = format!("${}", param_num);
2670 param_num += 1;
2671 ret
2672 } else {
2673 n
2674 }),
2675 token => token,
2676 };
2677 token_span
2678 })
2679 .unwrap();
2680 let actual = tokens.into_iter().map(|t| t.token).collect();
2681 let expected = vec![
2682 Token::make_keyword("SELECT"),
2683 Token::Whitespace(Whitespace::Space),
2684 Token::Placeholder("$1".to_string()),
2685 ];
2686
2687 compare(expected, actual);
2688 }
2689
2690 #[test]
2691 fn tokenize_clickhouse_double_equal() {
2692 let sql = String::from("SELECT foo=='1'");
2693 let dialect = ClickHouseDialect {};
2694 let mut tokenizer = Tokenizer::new(&dialect, &sql);
2695 let tokens = tokenizer.tokenize().unwrap();
2696
2697 let expected = vec![
2698 Token::make_keyword("SELECT"),
2699 Token::Whitespace(Whitespace::Space),
2700 Token::Word(Word {
2701 value: "foo".to_string(),
2702 quote_style: None,
2703 keyword: Keyword::NoKeyword,
2704 }),
2705 Token::DoubleEq,
2706 Token::SingleQuotedString("1".to_string()),
2707 ];
2708
2709 compare(expected, tokens);
2710 }
2711
2712 #[test]
2713 fn tokenize_numeric_literal_underscore() {
2714 let dialect = GenericDialect {};
2715 let sql = String::from("SELECT 10_000");
2716 let mut tokenizer = Tokenizer::new(&dialect, &sql);
2717 let tokens = tokenizer.tokenize().unwrap();
2718 let expected = vec![
2719 Token::make_keyword("SELECT"),
2720 Token::Whitespace(Whitespace::Space),
2721 Token::Number("10".to_string(), false),
2722 Token::make_word("_000", None),
2723 ];
2724 compare(expected, tokens);
2725
2726 all_dialects_where(|dialect| dialect.supports_numeric_literal_underscores()).tokenizes_to(
2727 "SELECT 10_000, _10_000, 10_00_, 10___0",
2728 vec![
2729 Token::make_keyword("SELECT"),
2730 Token::Whitespace(Whitespace::Space),
2731 Token::Number("10_000".to_string(), false),
2732 Token::Comma,
2733 Token::Whitespace(Whitespace::Space),
2734 Token::make_word("_10_000", None), Token::Comma,
2736 Token::Whitespace(Whitespace::Space),
2737 Token::Number("10_00".to_string(), false),
2738 Token::make_word("_", None), Token::Comma,
2740 Token::Whitespace(Whitespace::Space),
2741 Token::Number("10".to_string(), false),
2742 Token::make_word("___0", None), ],
2744 );
2745 }
2746
2747 #[test]
2748 fn tokenize_select_exponent() {
2749 let sql = String::from("SELECT 1e10, 1e-10, 1e+10, 1ea, 1e-10a, 1e-10-10");
2750 let dialect = GenericDialect {};
2751 let tokens = Tokenizer::new(&dialect, &sql).tokenize().unwrap();
2752
2753 let expected = vec![
2754 Token::make_keyword("SELECT"),
2755 Token::Whitespace(Whitespace::Space),
2756 Token::Number(String::from("1e10"), false),
2757 Token::Comma,
2758 Token::Whitespace(Whitespace::Space),
2759 Token::Number(String::from("1e-10"), false),
2760 Token::Comma,
2761 Token::Whitespace(Whitespace::Space),
2762 Token::Number(String::from("1e+10"), false),
2763 Token::Comma,
2764 Token::Whitespace(Whitespace::Space),
2765 Token::Number(String::from("1"), false),
2766 Token::make_word("ea", None),
2767 Token::Comma,
2768 Token::Whitespace(Whitespace::Space),
2769 Token::Number(String::from("1e-10"), false),
2770 Token::make_word("a", None),
2771 Token::Comma,
2772 Token::Whitespace(Whitespace::Space),
2773 Token::Number(String::from("1e-10"), false),
2774 Token::Minus,
2775 Token::Number(String::from("10"), false),
2776 ];
2777
2778 compare(expected, tokens);
2779 }
2780
2781 #[test]
2782 fn tokenize_scalar_function() {
2783 let sql = String::from("SELECT sqrt(1)");
2784 let dialect = GenericDialect {};
2785 let tokens = Tokenizer::new(&dialect, &sql).tokenize().unwrap();
2786
2787 let expected = vec![
2788 Token::make_keyword("SELECT"),
2789 Token::Whitespace(Whitespace::Space),
2790 Token::make_word("sqrt", None),
2791 Token::LParen,
2792 Token::Number(String::from("1"), false),
2793 Token::RParen,
2794 ];
2795
2796 compare(expected, tokens);
2797 }
2798
2799 #[test]
2800 fn tokenize_string_string_concat() {
2801 let sql = String::from("SELECT 'a' || 'b'");
2802 let dialect = GenericDialect {};
2803 let tokens = Tokenizer::new(&dialect, &sql).tokenize().unwrap();
2804
2805 let expected = vec![
2806 Token::make_keyword("SELECT"),
2807 Token::Whitespace(Whitespace::Space),
2808 Token::SingleQuotedString(String::from("a")),
2809 Token::Whitespace(Whitespace::Space),
2810 Token::StringConcat,
2811 Token::Whitespace(Whitespace::Space),
2812 Token::SingleQuotedString(String::from("b")),
2813 ];
2814
2815 compare(expected, tokens);
2816 }
2817 #[test]
2818 fn tokenize_bitwise_op() {
2819 let sql = String::from("SELECT one | two ^ three");
2820 let dialect = GenericDialect {};
2821 let tokens = Tokenizer::new(&dialect, &sql).tokenize().unwrap();
2822
2823 let expected = vec![
2824 Token::make_keyword("SELECT"),
2825 Token::Whitespace(Whitespace::Space),
2826 Token::make_word("one", None),
2827 Token::Whitespace(Whitespace::Space),
2828 Token::Pipe,
2829 Token::Whitespace(Whitespace::Space),
2830 Token::make_word("two", None),
2831 Token::Whitespace(Whitespace::Space),
2832 Token::Caret,
2833 Token::Whitespace(Whitespace::Space),
2834 Token::make_word("three", None),
2835 ];
2836 compare(expected, tokens);
2837 }
2838
2839 #[test]
2840 fn tokenize_logical_xor() {
2841 let sql =
2842 String::from("SELECT true XOR true, false XOR false, true XOR false, false XOR true");
2843 let dialect = GenericDialect {};
2844 let tokens = Tokenizer::new(&dialect, &sql).tokenize().unwrap();
2845
2846 let expected = vec![
2847 Token::make_keyword("SELECT"),
2848 Token::Whitespace(Whitespace::Space),
2849 Token::make_keyword("true"),
2850 Token::Whitespace(Whitespace::Space),
2851 Token::make_keyword("XOR"),
2852 Token::Whitespace(Whitespace::Space),
2853 Token::make_keyword("true"),
2854 Token::Comma,
2855 Token::Whitespace(Whitespace::Space),
2856 Token::make_keyword("false"),
2857 Token::Whitespace(Whitespace::Space),
2858 Token::make_keyword("XOR"),
2859 Token::Whitespace(Whitespace::Space),
2860 Token::make_keyword("false"),
2861 Token::Comma,
2862 Token::Whitespace(Whitespace::Space),
2863 Token::make_keyword("true"),
2864 Token::Whitespace(Whitespace::Space),
2865 Token::make_keyword("XOR"),
2866 Token::Whitespace(Whitespace::Space),
2867 Token::make_keyword("false"),
2868 Token::Comma,
2869 Token::Whitespace(Whitespace::Space),
2870 Token::make_keyword("false"),
2871 Token::Whitespace(Whitespace::Space),
2872 Token::make_keyword("XOR"),
2873 Token::Whitespace(Whitespace::Space),
2874 Token::make_keyword("true"),
2875 ];
2876 compare(expected, tokens);
2877 }
2878
2879 #[test]
2880 fn tokenize_simple_select() {
2881 let sql = String::from("SELECT * FROM customer WHERE id = 1 LIMIT 5");
2882 let dialect = GenericDialect {};
2883 let tokens = Tokenizer::new(&dialect, &sql).tokenize().unwrap();
2884
2885 let expected = vec![
2886 Token::make_keyword("SELECT"),
2887 Token::Whitespace(Whitespace::Space),
2888 Token::Mul,
2889 Token::Whitespace(Whitespace::Space),
2890 Token::make_keyword("FROM"),
2891 Token::Whitespace(Whitespace::Space),
2892 Token::make_word("customer", None),
2893 Token::Whitespace(Whitespace::Space),
2894 Token::make_keyword("WHERE"),
2895 Token::Whitespace(Whitespace::Space),
2896 Token::make_word("id", None),
2897 Token::Whitespace(Whitespace::Space),
2898 Token::Eq,
2899 Token::Whitespace(Whitespace::Space),
2900 Token::Number(String::from("1"), false),
2901 Token::Whitespace(Whitespace::Space),
2902 Token::make_keyword("LIMIT"),
2903 Token::Whitespace(Whitespace::Space),
2904 Token::Number(String::from("5"), false),
2905 ];
2906
2907 compare(expected, tokens);
2908 }
2909
2910 #[test]
2911 fn tokenize_explain_select() {
2912 let sql = String::from("EXPLAIN SELECT * FROM customer WHERE id = 1");
2913 let dialect = GenericDialect {};
2914 let tokens = Tokenizer::new(&dialect, &sql).tokenize().unwrap();
2915
2916 let expected = vec![
2917 Token::make_keyword("EXPLAIN"),
2918 Token::Whitespace(Whitespace::Space),
2919 Token::make_keyword("SELECT"),
2920 Token::Whitespace(Whitespace::Space),
2921 Token::Mul,
2922 Token::Whitespace(Whitespace::Space),
2923 Token::make_keyword("FROM"),
2924 Token::Whitespace(Whitespace::Space),
2925 Token::make_word("customer", None),
2926 Token::Whitespace(Whitespace::Space),
2927 Token::make_keyword("WHERE"),
2928 Token::Whitespace(Whitespace::Space),
2929 Token::make_word("id", None),
2930 Token::Whitespace(Whitespace::Space),
2931 Token::Eq,
2932 Token::Whitespace(Whitespace::Space),
2933 Token::Number(String::from("1"), false),
2934 ];
2935
2936 compare(expected, tokens);
2937 }
2938
2939 #[test]
2940 fn tokenize_explain_analyze_select() {
2941 let sql = String::from("EXPLAIN ANALYZE SELECT * FROM customer WHERE id = 1");
2942 let dialect = GenericDialect {};
2943 let tokens = Tokenizer::new(&dialect, &sql).tokenize().unwrap();
2944
2945 let expected = vec![
2946 Token::make_keyword("EXPLAIN"),
2947 Token::Whitespace(Whitespace::Space),
2948 Token::make_keyword("ANALYZE"),
2949 Token::Whitespace(Whitespace::Space),
2950 Token::make_keyword("SELECT"),
2951 Token::Whitespace(Whitespace::Space),
2952 Token::Mul,
2953 Token::Whitespace(Whitespace::Space),
2954 Token::make_keyword("FROM"),
2955 Token::Whitespace(Whitespace::Space),
2956 Token::make_word("customer", None),
2957 Token::Whitespace(Whitespace::Space),
2958 Token::make_keyword("WHERE"),
2959 Token::Whitespace(Whitespace::Space),
2960 Token::make_word("id", None),
2961 Token::Whitespace(Whitespace::Space),
2962 Token::Eq,
2963 Token::Whitespace(Whitespace::Space),
2964 Token::Number(String::from("1"), false),
2965 ];
2966
2967 compare(expected, tokens);
2968 }
2969
2970 #[test]
2971 fn tokenize_string_predicate() {
2972 let sql = String::from("SELECT * FROM customer WHERE salary != 'Not Provided'");
2973 let dialect = GenericDialect {};
2974 let tokens = Tokenizer::new(&dialect, &sql).tokenize().unwrap();
2975
2976 let expected = vec![
2977 Token::make_keyword("SELECT"),
2978 Token::Whitespace(Whitespace::Space),
2979 Token::Mul,
2980 Token::Whitespace(Whitespace::Space),
2981 Token::make_keyword("FROM"),
2982 Token::Whitespace(Whitespace::Space),
2983 Token::make_word("customer", None),
2984 Token::Whitespace(Whitespace::Space),
2985 Token::make_keyword("WHERE"),
2986 Token::Whitespace(Whitespace::Space),
2987 Token::make_word("salary", None),
2988 Token::Whitespace(Whitespace::Space),
2989 Token::Neq,
2990 Token::Whitespace(Whitespace::Space),
2991 Token::SingleQuotedString(String::from("Not Provided")),
2992 ];
2993
2994 compare(expected, tokens);
2995 }
2996
2997 #[test]
2998 fn tokenize_invalid_string() {
2999 let sql = String::from("\n💝مصطفىh");
3000
3001 let dialect = GenericDialect {};
3002 let tokens = Tokenizer::new(&dialect, &sql).tokenize().unwrap();
3003 let expected = vec![
3005 Token::Whitespace(Whitespace::Newline),
3006 Token::Char('💝'),
3007 Token::make_word("مصطفىh", None),
3008 ];
3009 compare(expected, tokens);
3010 }
3011
3012 #[test]
3013 fn tokenize_newline_in_string_literal() {
3014 let sql = String::from("'foo\r\nbar\nbaz'");
3015
3016 let dialect = GenericDialect {};
3017 let tokens = Tokenizer::new(&dialect, &sql).tokenize().unwrap();
3018 let expected = vec![Token::SingleQuotedString("foo\r\nbar\nbaz".to_string())];
3019 compare(expected, tokens);
3020 }
3021
3022 #[test]
3023 fn tokenize_unterminated_string_literal() {
3024 let sql = String::from("select 'foo");
3025
3026 let dialect = GenericDialect {};
3027 let mut tokenizer = Tokenizer::new(&dialect, &sql);
3028 assert_eq!(
3029 tokenizer.tokenize(),
3030 Err(TokenizerError {
3031 message: "Unterminated string literal".to_string(),
3032 location: Location { line: 1, column: 8 },
3033 })
3034 );
3035 }
3036
3037 #[test]
3038 fn tokenize_unterminated_string_literal_utf8() {
3039 let sql = String::from("SELECT \"なにか\" FROM Y WHERE \"なにか\" = 'test;");
3040
3041 let dialect = GenericDialect {};
3042 let mut tokenizer = Tokenizer::new(&dialect, &sql);
3043 assert_eq!(
3044 tokenizer.tokenize(),
3045 Err(TokenizerError {
3046 message: "Unterminated string literal".to_string(),
3047 location: Location {
3048 line: 1,
3049 column: 35
3050 }
3051 })
3052 );
3053 }
3054
3055 #[test]
3056 fn tokenize_invalid_string_cols() {
3057 let sql = String::from("\n\nSELECT * FROM table\t💝مصطفىh");
3058
3059 let dialect = GenericDialect {};
3060 let tokens = Tokenizer::new(&dialect, &sql).tokenize().unwrap();
3061 let expected = vec![
3063 Token::Whitespace(Whitespace::Newline),
3064 Token::Whitespace(Whitespace::Newline),
3065 Token::make_keyword("SELECT"),
3066 Token::Whitespace(Whitespace::Space),
3067 Token::Mul,
3068 Token::Whitespace(Whitespace::Space),
3069 Token::make_keyword("FROM"),
3070 Token::Whitespace(Whitespace::Space),
3071 Token::make_keyword("table"),
3072 Token::Whitespace(Whitespace::Tab),
3073 Token::Char('💝'),
3074 Token::make_word("مصطفىh", None),
3075 ];
3076 compare(expected, tokens);
3077 }
3078
3079 #[test]
3080 fn tokenize_dollar_quoted_string_tagged() {
3081 let test_cases = vec![
3082 (
3083 String::from("SELECT $tag$dollar '$' quoted strings have $tags like this$ or like this $$$tag$"),
3084 vec![
3085 Token::make_keyword("SELECT"),
3086 Token::Whitespace(Whitespace::Space),
3087 Token::DollarQuotedString(DollarQuotedString {
3088 value: "dollar '$' quoted strings have $tags like this$ or like this $$".into(),
3089 tag: Some("tag".into()),
3090 })
3091 ]
3092 ),
3093 (
3094 String::from("SELECT $abc$x$ab$abc$"),
3095 vec![
3096 Token::make_keyword("SELECT"),
3097 Token::Whitespace(Whitespace::Space),
3098 Token::DollarQuotedString(DollarQuotedString {
3099 value: "x$ab".into(),
3100 tag: Some("abc".into()),
3101 })
3102 ]
3103 ),
3104 (
3105 String::from("SELECT $abc$$abc$"),
3106 vec![
3107 Token::make_keyword("SELECT"),
3108 Token::Whitespace(Whitespace::Space),
3109 Token::DollarQuotedString(DollarQuotedString {
3110 value: "".into(),
3111 tag: Some("abc".into()),
3112 })
3113 ]
3114 ),
3115 (
3116 String::from("0$abc$$abc$1"),
3117 vec![
3118 Token::Number("0".into(), false),
3119 Token::DollarQuotedString(DollarQuotedString {
3120 value: "".into(),
3121 tag: Some("abc".into()),
3122 }),
3123 Token::Number("1".into(), false),
3124 ]
3125 ),
3126 (
3127 String::from("$function$abc$q$data$q$$function$"),
3128 vec![
3129 Token::DollarQuotedString(DollarQuotedString {
3130 value: "abc$q$data$q$".into(),
3131 tag: Some("function".into()),
3132 }),
3133 ]
3134 ),
3135 ];
3136
3137 let dialect = GenericDialect {};
3138 for (sql, expected) in test_cases {
3139 let tokens = Tokenizer::new(&dialect, &sql).tokenize().unwrap();
3140 compare(expected, tokens);
3141 }
3142 }
3143
3144 #[test]
3145 fn tokenize_dollar_quoted_string_tagged_unterminated() {
3146 let sql = String::from("SELECT $tag$dollar '$' quoted strings have $tags like this$ or like this $$$different tag$");
3147 let dialect = GenericDialect {};
3148 assert_eq!(
3149 Tokenizer::new(&dialect, &sql).tokenize(),
3150 Err(TokenizerError {
3151 message: "Unterminated dollar-quoted, expected $".into(),
3152 location: Location {
3153 line: 1,
3154 column: 91
3155 }
3156 })
3157 );
3158 }
3159
3160 #[test]
3161 fn tokenize_dollar_quoted_string_tagged_unterminated_mirror() {
3162 let sql = String::from("SELECT $abc$abc$");
3163 let dialect = GenericDialect {};
3164 assert_eq!(
3165 Tokenizer::new(&dialect, &sql).tokenize(),
3166 Err(TokenizerError {
3167 message: "Unterminated dollar-quoted, expected $".into(),
3168 location: Location {
3169 line: 1,
3170 column: 17
3171 }
3172 })
3173 );
3174 }
3175
3176 #[test]
3177 fn tokenize_dollar_placeholder() {
3178 let sql = String::from("SELECT $$, $$ABC$$, $ABC$, $ABC");
3179 let dialect = SQLiteDialect {};
3180 let tokens = Tokenizer::new(&dialect, &sql).tokenize().unwrap();
3181 assert_eq!(
3182 tokens,
3183 vec![
3184 Token::make_keyword("SELECT"),
3185 Token::Whitespace(Whitespace::Space),
3186 Token::Placeholder("$$".into()),
3187 Token::Comma,
3188 Token::Whitespace(Whitespace::Space),
3189 Token::Placeholder("$$ABC$$".into()),
3190 Token::Comma,
3191 Token::Whitespace(Whitespace::Space),
3192 Token::Placeholder("$ABC$".into()),
3193 Token::Comma,
3194 Token::Whitespace(Whitespace::Space),
3195 Token::Placeholder("$ABC".into()),
3196 ]
3197 );
3198 }
3199
3200 #[test]
3201 fn tokenize_nested_dollar_quoted_strings() {
3202 let sql = String::from("SELECT $tag$dollar $nested$ string$tag$");
3203 let dialect = GenericDialect {};
3204 let tokens = Tokenizer::new(&dialect, &sql).tokenize().unwrap();
3205 let expected = vec![
3206 Token::make_keyword("SELECT"),
3207 Token::Whitespace(Whitespace::Space),
3208 Token::DollarQuotedString(DollarQuotedString {
3209 value: "dollar $nested$ string".into(),
3210 tag: Some("tag".into()),
3211 }),
3212 ];
3213 compare(expected, tokens);
3214 }
3215
3216 #[test]
3217 fn tokenize_dollar_quoted_string_untagged_empty() {
3218 let sql = String::from("SELECT $$$$");
3219 let dialect = GenericDialect {};
3220 let tokens = Tokenizer::new(&dialect, &sql).tokenize().unwrap();
3221 let expected = vec![
3222 Token::make_keyword("SELECT"),
3223 Token::Whitespace(Whitespace::Space),
3224 Token::DollarQuotedString(DollarQuotedString {
3225 value: "".into(),
3226 tag: None,
3227 }),
3228 ];
3229 compare(expected, tokens);
3230 }
3231
3232 #[test]
3233 fn tokenize_dollar_quoted_string_untagged() {
3234 let sql =
3235 String::from("SELECT $$within dollar '$' quoted strings have $tags like this$ $$");
3236 let dialect = GenericDialect {};
3237 let tokens = Tokenizer::new(&dialect, &sql).tokenize().unwrap();
3238 let expected = vec![
3239 Token::make_keyword("SELECT"),
3240 Token::Whitespace(Whitespace::Space),
3241 Token::DollarQuotedString(DollarQuotedString {
3242 value: "within dollar '$' quoted strings have $tags like this$ ".into(),
3243 tag: None,
3244 }),
3245 ];
3246 compare(expected, tokens);
3247 }
3248
3249 #[test]
3250 fn tokenize_dollar_quoted_string_untagged_unterminated() {
3251 let sql = String::from(
3252 "SELECT $$dollar '$' quoted strings have $tags like this$ or like this $different tag$",
3253 );
3254 let dialect = GenericDialect {};
3255 assert_eq!(
3256 Tokenizer::new(&dialect, &sql).tokenize(),
3257 Err(TokenizerError {
3258 message: "Unterminated dollar-quoted string".into(),
3259 location: Location {
3260 line: 1,
3261 column: 86
3262 }
3263 })
3264 );
3265 }
3266
3267 #[test]
3268 fn tokenize_right_arrow() {
3269 let sql = String::from("FUNCTION(key=>value)");
3270 let dialect = GenericDialect {};
3271 let tokens = Tokenizer::new(&dialect, &sql).tokenize().unwrap();
3272 let expected = vec![
3273 Token::make_word("FUNCTION", None),
3274 Token::LParen,
3275 Token::make_word("key", None),
3276 Token::RArrow,
3277 Token::make_word("value", None),
3278 Token::RParen,
3279 ];
3280 compare(expected, tokens);
3281 }
3282
3283 #[test]
3284 fn tokenize_is_null() {
3285 let sql = String::from("a IS NULL");
3286 let dialect = GenericDialect {};
3287 let tokens = Tokenizer::new(&dialect, &sql).tokenize().unwrap();
3288
3289 let expected = vec![
3290 Token::make_word("a", None),
3291 Token::Whitespace(Whitespace::Space),
3292 Token::make_keyword("IS"),
3293 Token::Whitespace(Whitespace::Space),
3294 Token::make_keyword("NULL"),
3295 ];
3296
3297 compare(expected, tokens);
3298 }
3299
3300 #[test]
3301 fn tokenize_comment() {
3302 let test_cases = vec![
3303 (
3304 String::from("0--this is a comment\n1"),
3305 vec![
3306 Token::Number("0".to_string(), false),
3307 Token::Whitespace(Whitespace::SingleLineComment {
3308 prefix: "--".to_string(),
3309 comment: "this is a comment\n".to_string(),
3310 }),
3311 Token::Number("1".to_string(), false),
3312 ],
3313 ),
3314 (
3315 String::from("0--this is a comment\r1"),
3316 vec![
3317 Token::Number("0".to_string(), false),
3318 Token::Whitespace(Whitespace::SingleLineComment {
3319 prefix: "--".to_string(),
3320 comment: "this is a comment\r1".to_string(),
3321 }),
3322 ],
3323 ),
3324 (
3325 String::from("0--this is a comment\r\n1"),
3326 vec![
3327 Token::Number("0".to_string(), false),
3328 Token::Whitespace(Whitespace::SingleLineComment {
3329 prefix: "--".to_string(),
3330 comment: "this is a comment\r\n".to_string(),
3331 }),
3332 Token::Number("1".to_string(), false),
3333 ],
3334 ),
3335 ];
3336
3337 let dialect = GenericDialect {};
3338
3339 for (sql, expected) in test_cases {
3340 let tokens = Tokenizer::new(&dialect, &sql).tokenize().unwrap();
3341 compare(expected, tokens);
3342 }
3343 }
3344
3345 #[test]
3346 fn tokenize_comment_postgres() {
3347 let sql = String::from("1--\r0");
3348
3349 let dialect = PostgreSqlDialect {};
3350 let tokens = Tokenizer::new(&dialect, &sql).tokenize().unwrap();
3351 let expected = vec![
3352 Token::Number("1".to_string(), false),
3353 Token::Whitespace(Whitespace::SingleLineComment {
3354 prefix: "--".to_string(),
3355 comment: "\r".to_string(),
3356 }),
3357 Token::Number("0".to_string(), false),
3358 ];
3359 compare(expected, tokens);
3360 }
3361
3362 #[test]
3363 fn tokenize_comment_at_eof() {
3364 let sql = String::from("--this is a comment");
3365
3366 let dialect = GenericDialect {};
3367 let tokens = Tokenizer::new(&dialect, &sql).tokenize().unwrap();
3368 let expected = vec![Token::Whitespace(Whitespace::SingleLineComment {
3369 prefix: "--".to_string(),
3370 comment: "this is a comment".to_string(),
3371 })];
3372 compare(expected, tokens);
3373 }
3374
3375 #[test]
3376 fn tokenize_multiline_comment() {
3377 let sql = String::from("0/*multi-line\n* /comment*/1");
3378
3379 let dialect = GenericDialect {};
3380 let tokens = Tokenizer::new(&dialect, &sql).tokenize().unwrap();
3381 let expected = vec![
3382 Token::Number("0".to_string(), false),
3383 Token::Whitespace(Whitespace::MultiLineComment(
3384 "multi-line\n* /comment".to_string(),
3385 )),
3386 Token::Number("1".to_string(), false),
3387 ];
3388 compare(expected, tokens);
3389 }
3390
3391 #[test]
3392 fn tokenize_nested_multiline_comment() {
3393 all_dialects_where(|d| d.supports_nested_comments()).tokenizes_to(
3394 "0/*multi-line\n* \n/* comment \n /*comment*/*/ */ /comment*/1",
3395 vec![
3396 Token::Number("0".to_string(), false),
3397 Token::Whitespace(Whitespace::MultiLineComment(
3398 "multi-line\n* \n/* comment \n /*comment*/*/ ".into(),
3399 )),
3400 Token::Whitespace(Whitespace::Space),
3401 Token::Div,
3402 Token::Word(Word {
3403 value: "comment".to_string(),
3404 quote_style: None,
3405 keyword: Keyword::COMMENT,
3406 }),
3407 Token::Mul,
3408 Token::Div,
3409 Token::Number("1".to_string(), false),
3410 ],
3411 );
3412
3413 all_dialects_where(|d| d.supports_nested_comments()).tokenizes_to(
3414 "0/*multi-line\n* \n/* comment \n /*comment/**/ */ /comment*/*/1",
3415 vec![
3416 Token::Number("0".to_string(), false),
3417 Token::Whitespace(Whitespace::MultiLineComment(
3418 "multi-line\n* \n/* comment \n /*comment/**/ */ /comment*/".into(),
3419 )),
3420 Token::Number("1".to_string(), false),
3421 ],
3422 );
3423
3424 all_dialects_where(|d| d.supports_nested_comments()).tokenizes_to(
3425 "SELECT 1/* a /* b */ c */0",
3426 vec![
3427 Token::make_keyword("SELECT"),
3428 Token::Whitespace(Whitespace::Space),
3429 Token::Number("1".to_string(), false),
3430 Token::Whitespace(Whitespace::MultiLineComment(" a /* b */ c ".to_string())),
3431 Token::Number("0".to_string(), false),
3432 ],
3433 );
3434 }
3435
3436 #[test]
3437 fn tokenize_nested_multiline_comment_empty() {
3438 all_dialects_where(|d| d.supports_nested_comments()).tokenizes_to(
3439 "select 1/*/**/*/0",
3440 vec![
3441 Token::make_keyword("select"),
3442 Token::Whitespace(Whitespace::Space),
3443 Token::Number("1".to_string(), false),
3444 Token::Whitespace(Whitespace::MultiLineComment("/**/".to_string())),
3445 Token::Number("0".to_string(), false),
3446 ],
3447 );
3448 }
3449
3450 #[test]
3451 fn tokenize_nested_comments_if_not_supported() {
3452 all_dialects_except(|d| d.supports_nested_comments()).tokenizes_to(
3453 "SELECT 1/*/* nested comment */*/0",
3454 vec![
3455 Token::make_keyword("SELECT"),
3456 Token::Whitespace(Whitespace::Space),
3457 Token::Number("1".to_string(), false),
3458 Token::Whitespace(Whitespace::MultiLineComment(
3459 "/* nested comment ".to_string(),
3460 )),
3461 Token::Mul,
3462 Token::Div,
3463 Token::Number("0".to_string(), false),
3464 ],
3465 );
3466 }
3467
3468 #[test]
3469 fn tokenize_multiline_comment_with_even_asterisks() {
3470 let sql = String::from("\n/** Comment **/\n");
3471
3472 let dialect = GenericDialect {};
3473 let tokens = Tokenizer::new(&dialect, &sql).tokenize().unwrap();
3474 let expected = vec![
3475 Token::Whitespace(Whitespace::Newline),
3476 Token::Whitespace(Whitespace::MultiLineComment("* Comment *".to_string())),
3477 Token::Whitespace(Whitespace::Newline),
3478 ];
3479 compare(expected, tokens);
3480 }
3481
3482 #[test]
3483 fn tokenize_unicode_whitespace() {
3484 let sql = String::from(" \u{2003}\n");
3485
3486 let dialect = GenericDialect {};
3487 let tokens = Tokenizer::new(&dialect, &sql).tokenize().unwrap();
3488 let expected = vec![
3489 Token::Whitespace(Whitespace::Space),
3490 Token::Whitespace(Whitespace::Space),
3491 Token::Whitespace(Whitespace::Newline),
3492 ];
3493 compare(expected, tokens);
3494 }
3495
3496 #[test]
3497 fn tokenize_mismatched_quotes() {
3498 let sql = String::from("\"foo");
3499
3500 let dialect = GenericDialect {};
3501 let mut tokenizer = Tokenizer::new(&dialect, &sql);
3502 assert_eq!(
3503 tokenizer.tokenize(),
3504 Err(TokenizerError {
3505 message: "Expected close delimiter '\"' before EOF.".to_string(),
3506 location: Location { line: 1, column: 1 },
3507 })
3508 );
3509 }
3510
3511 #[test]
3512 fn tokenize_newlines() {
3513 let sql = String::from("line1\nline2\rline3\r\nline4\r");
3514
3515 let dialect = GenericDialect {};
3516 let tokens = Tokenizer::new(&dialect, &sql).tokenize().unwrap();
3517 let expected = vec![
3518 Token::make_word("line1", None),
3519 Token::Whitespace(Whitespace::Newline),
3520 Token::make_word("line2", None),
3521 Token::Whitespace(Whitespace::Newline),
3522 Token::make_word("line3", None),
3523 Token::Whitespace(Whitespace::Newline),
3524 Token::make_word("line4", None),
3525 Token::Whitespace(Whitespace::Newline),
3526 ];
3527 compare(expected, tokens);
3528 }
3529
3530 #[test]
3531 fn tokenize_mssql_top() {
3532 let sql = "SELECT TOP 5 [bar] FROM foo";
3533 let dialect = MsSqlDialect {};
3534 let tokens = Tokenizer::new(&dialect, sql).tokenize().unwrap();
3535 let expected = vec![
3536 Token::make_keyword("SELECT"),
3537 Token::Whitespace(Whitespace::Space),
3538 Token::make_keyword("TOP"),
3539 Token::Whitespace(Whitespace::Space),
3540 Token::Number(String::from("5"), false),
3541 Token::Whitespace(Whitespace::Space),
3542 Token::make_word("bar", Some('[')),
3543 Token::Whitespace(Whitespace::Space),
3544 Token::make_keyword("FROM"),
3545 Token::Whitespace(Whitespace::Space),
3546 Token::make_word("foo", None),
3547 ];
3548 compare(expected, tokens);
3549 }
3550
3551 #[test]
3552 fn tokenize_pg_regex_match() {
3553 let sql = "SELECT col ~ '^a', col ~* '^a', col !~ '^a', col !~* '^a'";
3554 let dialect = GenericDialect {};
3555 let tokens = Tokenizer::new(&dialect, sql).tokenize().unwrap();
3556 let expected = vec![
3557 Token::make_keyword("SELECT"),
3558 Token::Whitespace(Whitespace::Space),
3559 Token::make_word("col", None),
3560 Token::Whitespace(Whitespace::Space),
3561 Token::Tilde,
3562 Token::Whitespace(Whitespace::Space),
3563 Token::SingleQuotedString("^a".into()),
3564 Token::Comma,
3565 Token::Whitespace(Whitespace::Space),
3566 Token::make_word("col", None),
3567 Token::Whitespace(Whitespace::Space),
3568 Token::TildeAsterisk,
3569 Token::Whitespace(Whitespace::Space),
3570 Token::SingleQuotedString("^a".into()),
3571 Token::Comma,
3572 Token::Whitespace(Whitespace::Space),
3573 Token::make_word("col", None),
3574 Token::Whitespace(Whitespace::Space),
3575 Token::ExclamationMarkTilde,
3576 Token::Whitespace(Whitespace::Space),
3577 Token::SingleQuotedString("^a".into()),
3578 Token::Comma,
3579 Token::Whitespace(Whitespace::Space),
3580 Token::make_word("col", None),
3581 Token::Whitespace(Whitespace::Space),
3582 Token::ExclamationMarkTildeAsterisk,
3583 Token::Whitespace(Whitespace::Space),
3584 Token::SingleQuotedString("^a".into()),
3585 ];
3586 compare(expected, tokens);
3587 }
3588
3589 #[test]
3590 fn tokenize_pg_like_match() {
3591 let sql = "SELECT col ~~ '_a%', col ~~* '_a%', col !~~ '_a%', col !~~* '_a%'";
3592 let dialect = GenericDialect {};
3593 let tokens = Tokenizer::new(&dialect, sql).tokenize().unwrap();
3594 let expected = vec![
3595 Token::make_keyword("SELECT"),
3596 Token::Whitespace(Whitespace::Space),
3597 Token::make_word("col", None),
3598 Token::Whitespace(Whitespace::Space),
3599 Token::DoubleTilde,
3600 Token::Whitespace(Whitespace::Space),
3601 Token::SingleQuotedString("_a%".into()),
3602 Token::Comma,
3603 Token::Whitespace(Whitespace::Space),
3604 Token::make_word("col", None),
3605 Token::Whitespace(Whitespace::Space),
3606 Token::DoubleTildeAsterisk,
3607 Token::Whitespace(Whitespace::Space),
3608 Token::SingleQuotedString("_a%".into()),
3609 Token::Comma,
3610 Token::Whitespace(Whitespace::Space),
3611 Token::make_word("col", None),
3612 Token::Whitespace(Whitespace::Space),
3613 Token::ExclamationMarkDoubleTilde,
3614 Token::Whitespace(Whitespace::Space),
3615 Token::SingleQuotedString("_a%".into()),
3616 Token::Comma,
3617 Token::Whitespace(Whitespace::Space),
3618 Token::make_word("col", None),
3619 Token::Whitespace(Whitespace::Space),
3620 Token::ExclamationMarkDoubleTildeAsterisk,
3621 Token::Whitespace(Whitespace::Space),
3622 Token::SingleQuotedString("_a%".into()),
3623 ];
3624 compare(expected, tokens);
3625 }
3626
3627 #[test]
3628 fn tokenize_quoted_identifier() {
3629 let sql = r#" "a "" b" "a """ "c """"" "#;
3630 let dialect = GenericDialect {};
3631 let tokens = Tokenizer::new(&dialect, sql).tokenize().unwrap();
3632 let expected = vec![
3633 Token::Whitespace(Whitespace::Space),
3634 Token::make_word(r#"a " b"#, Some('"')),
3635 Token::Whitespace(Whitespace::Space),
3636 Token::make_word(r#"a ""#, Some('"')),
3637 Token::Whitespace(Whitespace::Space),
3638 Token::make_word(r#"c """#, Some('"')),
3639 Token::Whitespace(Whitespace::Space),
3640 ];
3641 compare(expected, tokens);
3642 }
3643
3644 #[test]
3645 fn tokenize_snowflake_div() {
3646 let sql = r#"field/1000"#;
3647 let dialect = SnowflakeDialect {};
3648 let tokens = Tokenizer::new(&dialect, sql).tokenize().unwrap();
3649 let expected = vec![
3650 Token::make_word(r#"field"#, None),
3651 Token::Div,
3652 Token::Number("1000".to_string(), false),
3653 ];
3654 compare(expected, tokens);
3655 }
3656
3657 #[test]
3658 fn tokenize_quoted_identifier_with_no_escape() {
3659 let sql = r#" "a "" b" "a """ "c """"" "#;
3660 let dialect = GenericDialect {};
3661 let tokens = Tokenizer::new(&dialect, sql)
3662 .with_unescape(false)
3663 .tokenize()
3664 .unwrap();
3665 let expected = vec![
3666 Token::Whitespace(Whitespace::Space),
3667 Token::make_word(r#"a "" b"#, Some('"')),
3668 Token::Whitespace(Whitespace::Space),
3669 Token::make_word(r#"a """#, Some('"')),
3670 Token::Whitespace(Whitespace::Space),
3671 Token::make_word(r#"c """""#, Some('"')),
3672 Token::Whitespace(Whitespace::Space),
3673 ];
3674 compare(expected, tokens);
3675 }
3676
3677 #[test]
3678 fn tokenize_with_location() {
3679 let sql = "SELECT a,\n b";
3680 let dialect = GenericDialect {};
3681 let tokens = Tokenizer::new(&dialect, sql)
3682 .tokenize_with_location()
3683 .unwrap();
3684 let expected = vec![
3685 TokenWithSpan::at(Token::make_keyword("SELECT"), (1, 1).into(), (1, 7).into()),
3686 TokenWithSpan::at(
3687 Token::Whitespace(Whitespace::Space),
3688 (1, 7).into(),
3689 (1, 8).into(),
3690 ),
3691 TokenWithSpan::at(Token::make_word("a", None), (1, 8).into(), (1, 9).into()),
3692 TokenWithSpan::at(Token::Comma, (1, 9).into(), (1, 10).into()),
3693 TokenWithSpan::at(
3694 Token::Whitespace(Whitespace::Newline),
3695 (1, 10).into(),
3696 (2, 1).into(),
3697 ),
3698 TokenWithSpan::at(
3699 Token::Whitespace(Whitespace::Space),
3700 (2, 1).into(),
3701 (2, 2).into(),
3702 ),
3703 TokenWithSpan::at(Token::make_word("b", None), (2, 2).into(), (2, 3).into()),
3704 ];
3705 compare(expected, tokens);
3706 }
3707
3708 fn compare<T: PartialEq + fmt::Debug>(expected: Vec<T>, actual: Vec<T>) {
3709 assert_eq!(expected, actual);
3714 }
3715
3716 fn check_unescape(s: &str, expected: Option<&str>) {
3717 let s = format!("'{s}'");
3718 let mut state = State {
3719 peekable: s.chars().peekable(),
3720 line: 0,
3721 col: 0,
3722 };
3723
3724 assert_eq!(
3725 unescape_single_quoted_string(&mut state),
3726 expected.map(|s| s.to_string())
3727 );
3728 }
3729
3730 #[test]
3731 fn test_unescape() {
3732 check_unescape(r"\b", Some("\u{0008}"));
3733 check_unescape(r"\f", Some("\u{000C}"));
3734 check_unescape(r"\t", Some("\t"));
3735 check_unescape(r"\r\n", Some("\r\n"));
3736 check_unescape(r"\/", Some("/"));
3737 check_unescape(r"/", Some("/"));
3738 check_unescape(r"\\", Some("\\"));
3739
3740 check_unescape(r"\u0001", Some("\u{0001}"));
3742 check_unescape(r"\u4c91", Some("\u{4c91}"));
3743 check_unescape(r"\u4c916", Some("\u{4c91}6"));
3744 check_unescape(r"\u4c", None);
3745 check_unescape(r"\u0000", None);
3746 check_unescape(r"\U0010FFFF", Some("\u{10FFFF}"));
3747 check_unescape(r"\U00110000", None);
3748 check_unescape(r"\U00000000", None);
3749 check_unescape(r"\u", None);
3750 check_unescape(r"\U", None);
3751 check_unescape(r"\U1010FFFF", None);
3752
3753 check_unescape(r"\x4B", Some("\u{004b}"));
3755 check_unescape(r"\x4", Some("\u{0004}"));
3756 check_unescape(r"\x4L", Some("\u{0004}L"));
3757 check_unescape(r"\x", Some("x"));
3758 check_unescape(r"\xP", Some("xP"));
3759 check_unescape(r"\x0", None);
3760 check_unescape(r"\xCAD", None);
3761 check_unescape(r"\xA9", None);
3762
3763 check_unescape(r"\1", Some("\u{0001}"));
3765 check_unescape(r"\12", Some("\u{000a}"));
3766 check_unescape(r"\123", Some("\u{0053}"));
3767 check_unescape(r"\1232", Some("\u{0053}2"));
3768 check_unescape(r"\4", Some("\u{0004}"));
3769 check_unescape(r"\45", Some("\u{0025}"));
3770 check_unescape(r"\450", Some("\u{0028}"));
3771 check_unescape(r"\603", None);
3772 check_unescape(r"\0", None);
3773 check_unescape(r"\080", None);
3774
3775 check_unescape(r"\9", Some("9"));
3777 check_unescape(r"''", Some("'"));
3778 check_unescape(
3779 r"Hello\r\nRust/\u4c91 SQL Parser\U0010ABCD\1232",
3780 Some("Hello\r\nRust/\u{4c91} SQL Parser\u{10abcd}\u{0053}2"),
3781 );
3782 check_unescape(r"Hello\0", None);
3783 check_unescape(r"Hello\xCADRust", None);
3784 }
3785
3786 #[test]
3787 fn tokenize_numeric_prefix_trait() {
3788 #[derive(Debug)]
3789 struct NumericPrefixDialect;
3790
3791 impl Dialect for NumericPrefixDialect {
3792 fn is_identifier_start(&self, ch: char) -> bool {
3793 ch.is_ascii_lowercase()
3794 || ch.is_ascii_uppercase()
3795 || ch.is_ascii_digit()
3796 || ch == '$'
3797 }
3798
3799 fn is_identifier_part(&self, ch: char) -> bool {
3800 ch.is_ascii_lowercase()
3801 || ch.is_ascii_uppercase()
3802 || ch.is_ascii_digit()
3803 || ch == '_'
3804 || ch == '$'
3805 || ch == '{'
3806 || ch == '}'
3807 }
3808
3809 fn supports_numeric_prefix(&self) -> bool {
3810 true
3811 }
3812 }
3813
3814 tokenize_numeric_prefix_inner(&NumericPrefixDialect {});
3815 tokenize_numeric_prefix_inner(&HiveDialect {});
3816 tokenize_numeric_prefix_inner(&MySqlDialect {});
3817 }
3818
3819 fn tokenize_numeric_prefix_inner(dialect: &dyn Dialect) {
3820 let sql = r#"SELECT * FROM 1"#;
3821 let tokens = Tokenizer::new(dialect, sql).tokenize().unwrap();
3822 let expected = vec![
3823 Token::make_keyword("SELECT"),
3824 Token::Whitespace(Whitespace::Space),
3825 Token::Mul,
3826 Token::Whitespace(Whitespace::Space),
3827 Token::make_keyword("FROM"),
3828 Token::Whitespace(Whitespace::Space),
3829 Token::Number(String::from("1"), false),
3830 ];
3831 compare(expected, tokens);
3832 }
3833
3834 #[test]
3835 fn tokenize_quoted_string_escape() {
3836 let dialect = SnowflakeDialect {};
3837 for (sql, expected, expected_unescaped) in [
3838 (r#"'%a\'%b'"#, r#"%a\'%b"#, r#"%a'%b"#),
3839 (r#"'a\'\'b\'c\'d'"#, r#"a\'\'b\'c\'d"#, r#"a''b'c'd"#),
3840 (r#"'\\'"#, r#"\\"#, r#"\"#),
3841 (
3842 r#"'\0\a\b\f\n\r\t\Z'"#,
3843 r#"\0\a\b\f\n\r\t\Z"#,
3844 "\0\u{7}\u{8}\u{c}\n\r\t\u{1a}",
3845 ),
3846 (r#"'\"'"#, r#"\""#, "\""),
3847 (r#"'\\a\\b\'c'"#, r#"\\a\\b\'c"#, r#"\a\b'c"#),
3848 (r#"'\'abcd'"#, r#"\'abcd"#, r#"'abcd"#),
3849 (r#"'''a''b'"#, r#"''a''b"#, r#"'a'b"#),
3850 (r#"'\q'"#, r#"\q"#, r#"q"#),
3851 (r#"'\%\_'"#, r#"\%\_"#, r#"%_"#),
3852 (r#"'\\%\\_'"#, r#"\\%\\_"#, r#"\%\_"#),
3853 ] {
3854 let tokens = Tokenizer::new(&dialect, sql)
3855 .with_unescape(false)
3856 .tokenize()
3857 .unwrap();
3858 let expected = vec![Token::SingleQuotedString(expected.to_string())];
3859 compare(expected, tokens);
3860
3861 let tokens = Tokenizer::new(&dialect, sql)
3862 .with_unescape(true)
3863 .tokenize()
3864 .unwrap();
3865 let expected = vec![Token::SingleQuotedString(expected_unescaped.to_string())];
3866 compare(expected, tokens);
3867 }
3868
3869 for sql in [r#"'\'"#, r#"'ab\'"#] {
3870 let mut tokenizer = Tokenizer::new(&dialect, sql);
3871 assert_eq!(
3872 "Unterminated string literal",
3873 tokenizer.tokenize().unwrap_err().message.as_str(),
3874 );
3875 }
3876
3877 for (sql, expected) in [(r#"'\'"#, r#"\"#), (r#"'ab\'"#, r#"ab\"#)] {
3879 let dialect = GenericDialect {};
3880 let tokens = Tokenizer::new(&dialect, sql).tokenize().unwrap();
3881
3882 let expected = vec![Token::SingleQuotedString(expected.to_string())];
3883
3884 compare(expected, tokens);
3885 }
3886
3887 for (sql, expected) in [(r#"'\%'"#, r#"\%"#), (r#"'\_'"#, r#"\_"#)] {
3889 let dialect = MySqlDialect {};
3890 let tokens = Tokenizer::new(&dialect, sql).tokenize().unwrap();
3891
3892 let expected = vec![Token::SingleQuotedString(expected.to_string())];
3893
3894 compare(expected, tokens);
3895 }
3896 }
3897
3898 #[test]
3899 fn tokenize_triple_quoted_string() {
3900 fn check<F>(
3901 q: char, r: char, quote_token: F,
3904 ) where
3905 F: Fn(String) -> Token,
3906 {
3907 let dialect = BigQueryDialect {};
3908
3909 for (sql, expected, expected_unescaped) in [
3910 (format!(r#"{q}{q}{q}{q}{q}{q}"#), "".into(), "".into()),
3912 (
3914 format!(r#"{q}{q}{q}ab{q}{q}\{q}{q}cd{q}{q}{q}"#),
3915 format!(r#"ab{q}{q}\{q}{q}cd"#),
3916 format!(r#"ab{q}{q}{q}{q}cd"#),
3917 ),
3918 (
3920 format!(r#"{q}{q}{q}abc{q}{q}{q}"#),
3921 "abc".into(),
3922 "abc".into(),
3923 ),
3924 (
3926 format!(r#"{q}{q}{q}ab{r}{r}{r}c{r}def{r}{r}{r}{q}{q}{q}"#),
3927 format!("ab{r}{r}{r}c{r}def{r}{r}{r}"),
3928 format!("ab{r}{r}{r}c{r}def{r}{r}{r}"),
3929 ),
3930 (
3932 format!(r#"{q}{q}{q}ab{q}{q}c{q}{q}\{q}de{q}{q}f{q}{q}{q}"#),
3933 format!(r#"ab{q}{q}c{q}{q}\{q}de{q}{q}f"#),
3934 format!(r#"ab{q}{q}c{q}{q}{q}de{q}{q}f"#),
3935 ),
3936 (
3938 format!(r#"{q}{q}{q}a\'\'b\'c\'d{q}{q}{q}"#),
3939 r#"a\'\'b\'c\'d"#.into(),
3940 r#"a''b'c'd"#.into(),
3941 ),
3942 (
3944 format!(r#"{q}{q}{q}abc\0\n\rdef{q}{q}{q}"#),
3945 r#"abc\0\n\rdef"#.into(),
3946 "abc\0\n\rdef".into(),
3947 ),
3948 ] {
3949 let tokens = Tokenizer::new(&dialect, sql.as_str())
3950 .with_unescape(false)
3951 .tokenize()
3952 .unwrap();
3953 let expected = vec![quote_token(expected.to_string())];
3954 compare(expected, tokens);
3955
3956 let tokens = Tokenizer::new(&dialect, sql.as_str())
3957 .with_unescape(true)
3958 .tokenize()
3959 .unwrap();
3960 let expected = vec![quote_token(expected_unescaped.to_string())];
3961 compare(expected, tokens);
3962 }
3963
3964 for sql in [
3965 format!(r#"{q}{q}{q}{q}{q}\{q}"#),
3966 format!(r#"{q}{q}{q}abc{q}{q}\{q}"#),
3967 format!(r#"{q}{q}{q}{q}"#),
3968 format!(r#"{q}{q}{q}{r}{r}"#),
3969 format!(r#"{q}{q}{q}abc{q}"#),
3970 format!(r#"{q}{q}{q}abc{q}{q}"#),
3971 format!(r#"{q}{q}{q}abc"#),
3972 ] {
3973 let dialect = BigQueryDialect {};
3974 let mut tokenizer = Tokenizer::new(&dialect, sql.as_str());
3975 assert_eq!(
3976 "Unterminated string literal",
3977 tokenizer.tokenize().unwrap_err().message.as_str(),
3978 );
3979 }
3980 }
3981
3982 check('"', '\'', Token::TripleDoubleQuotedString);
3983
3984 check('\'', '"', Token::TripleSingleQuotedString);
3985
3986 let dialect = BigQueryDialect {};
3987
3988 let sql = r#"""''"#;
3989 let tokens = Tokenizer::new(&dialect, sql)
3990 .with_unescape(true)
3991 .tokenize()
3992 .unwrap();
3993 let expected = vec![
3994 Token::DoubleQuotedString("".to_string()),
3995 Token::SingleQuotedString("".to_string()),
3996 ];
3997 compare(expected, tokens);
3998
3999 let sql = r#"''"""#;
4000 let tokens = Tokenizer::new(&dialect, sql)
4001 .with_unescape(true)
4002 .tokenize()
4003 .unwrap();
4004 let expected = vec![
4005 Token::SingleQuotedString("".to_string()),
4006 Token::DoubleQuotedString("".to_string()),
4007 ];
4008 compare(expected, tokens);
4009
4010 let dialect = SnowflakeDialect {};
4012 let sql = r#"''''''"#;
4013 let tokens = Tokenizer::new(&dialect, sql).tokenize().unwrap();
4014 let expected = vec![Token::SingleQuotedString("''".to_string())];
4015 compare(expected, tokens);
4016 }
4017
4018 #[test]
4019 fn test_mysql_users_grantees() {
4020 let dialect = MySqlDialect {};
4021
4022 let sql = "CREATE USER `root`@`%`";
4023 let tokens = Tokenizer::new(&dialect, sql).tokenize().unwrap();
4024 let expected = vec![
4025 Token::make_keyword("CREATE"),
4026 Token::Whitespace(Whitespace::Space),
4027 Token::make_keyword("USER"),
4028 Token::Whitespace(Whitespace::Space),
4029 Token::make_word("root", Some('`')),
4030 Token::AtSign,
4031 Token::make_word("%", Some('`')),
4032 ];
4033 compare(expected, tokens);
4034 }
4035
4036 #[test]
4037 fn test_postgres_abs_without_space_and_string_literal() {
4038 let dialect = MySqlDialect {};
4039
4040 let sql = "SELECT @'1'";
4041 let tokens = Tokenizer::new(&dialect, sql).tokenize().unwrap();
4042 let expected = vec![
4043 Token::make_keyword("SELECT"),
4044 Token::Whitespace(Whitespace::Space),
4045 Token::AtSign,
4046 Token::SingleQuotedString("1".to_string()),
4047 ];
4048 compare(expected, tokens);
4049 }
4050
4051 #[test]
4052 fn test_postgres_abs_without_space_and_quoted_column() {
4053 let dialect = MySqlDialect {};
4054
4055 let sql = r#"SELECT @"bar" FROM foo"#;
4056 let tokens = Tokenizer::new(&dialect, sql).tokenize().unwrap();
4057 let expected = vec![
4058 Token::make_keyword("SELECT"),
4059 Token::Whitespace(Whitespace::Space),
4060 Token::AtSign,
4061 Token::DoubleQuotedString("bar".to_string()),
4062 Token::Whitespace(Whitespace::Space),
4063 Token::make_keyword("FROM"),
4064 Token::Whitespace(Whitespace::Space),
4065 Token::make_word("foo", None),
4066 ];
4067 compare(expected, tokens);
4068 }
4069
4070 #[test]
4071 fn test_national_strings_backslash_escape_not_supported() {
4072 all_dialects_where(|dialect| !dialect.supports_string_literal_backslash_escape())
4073 .tokenizes_to(
4074 "select n'''''\\'",
4075 vec![
4076 Token::make_keyword("select"),
4077 Token::Whitespace(Whitespace::Space),
4078 Token::NationalStringLiteral("''\\".to_string()),
4079 ],
4080 );
4081 }
4082
4083 #[test]
4084 fn test_national_strings_backslash_escape_supported() {
4085 all_dialects_where(|dialect| dialect.supports_string_literal_backslash_escape())
4086 .tokenizes_to(
4087 "select n'''''\\''",
4088 vec![
4089 Token::make_keyword("select"),
4090 Token::Whitespace(Whitespace::Space),
4091 Token::NationalStringLiteral("'''".to_string()),
4092 ],
4093 );
4094 }
4095
4096 #[test]
4097 fn test_string_escape_constant_not_supported() {
4098 all_dialects_where(|dialect| !dialect.supports_string_escape_constant()).tokenizes_to(
4099 "select e'...'",
4100 vec![
4101 Token::make_keyword("select"),
4102 Token::Whitespace(Whitespace::Space),
4103 Token::make_word("e", None),
4104 Token::SingleQuotedString("...".to_string()),
4105 ],
4106 );
4107
4108 all_dialects_where(|dialect| !dialect.supports_string_escape_constant()).tokenizes_to(
4109 "select E'...'",
4110 vec![
4111 Token::make_keyword("select"),
4112 Token::Whitespace(Whitespace::Space),
4113 Token::make_word("E", None),
4114 Token::SingleQuotedString("...".to_string()),
4115 ],
4116 );
4117 }
4118
4119 #[test]
4120 fn test_string_escape_constant_supported() {
4121 all_dialects_where(|dialect| dialect.supports_string_escape_constant()).tokenizes_to(
4122 "select e'\\''",
4123 vec![
4124 Token::make_keyword("select"),
4125 Token::Whitespace(Whitespace::Space),
4126 Token::EscapedStringLiteral("'".to_string()),
4127 ],
4128 );
4129
4130 all_dialects_where(|dialect| dialect.supports_string_escape_constant()).tokenizes_to(
4131 "select E'\\''",
4132 vec![
4133 Token::make_keyword("select"),
4134 Token::Whitespace(Whitespace::Space),
4135 Token::EscapedStringLiteral("'".to_string()),
4136 ],
4137 );
4138 }
4139
4140 #[test]
4141 fn test_whitespace_required_after_single_line_comment() {
4142 all_dialects_where(|dialect| dialect.requires_single_line_comment_whitespace())
4143 .tokenizes_to(
4144 "SELECT --'abc'",
4145 vec![
4146 Token::make_keyword("SELECT"),
4147 Token::Whitespace(Whitespace::Space),
4148 Token::Minus,
4149 Token::Minus,
4150 Token::SingleQuotedString("abc".to_string()),
4151 ],
4152 );
4153
4154 all_dialects_where(|dialect| dialect.requires_single_line_comment_whitespace())
4155 .tokenizes_to(
4156 "SELECT -- 'abc'",
4157 vec![
4158 Token::make_keyword("SELECT"),
4159 Token::Whitespace(Whitespace::Space),
4160 Token::Whitespace(Whitespace::SingleLineComment {
4161 prefix: "--".to_string(),
4162 comment: " 'abc'".to_string(),
4163 }),
4164 ],
4165 );
4166
4167 all_dialects_where(|dialect| dialect.requires_single_line_comment_whitespace())
4168 .tokenizes_to(
4169 "SELECT --",
4170 vec![
4171 Token::make_keyword("SELECT"),
4172 Token::Whitespace(Whitespace::Space),
4173 Token::Minus,
4174 Token::Minus,
4175 ],
4176 );
4177
4178 all_dialects_where(|d| d.requires_single_line_comment_whitespace()).tokenizes_to(
4179 "--\n-- Table structure for table...\n--\n",
4180 vec![
4181 Token::Whitespace(Whitespace::SingleLineComment {
4182 prefix: "--".to_string(),
4183 comment: "\n".to_string(),
4184 }),
4185 Token::Whitespace(Whitespace::SingleLineComment {
4186 prefix: "--".to_string(),
4187 comment: " Table structure for table...\n".to_string(),
4188 }),
4189 Token::Whitespace(Whitespace::SingleLineComment {
4190 prefix: "--".to_string(),
4191 comment: "\n".to_string(),
4192 }),
4193 ],
4194 );
4195 }
4196
4197 #[test]
4198 fn test_whitespace_not_required_after_single_line_comment() {
4199 all_dialects_where(|dialect| !dialect.requires_single_line_comment_whitespace())
4200 .tokenizes_to(
4201 "SELECT --'abc'",
4202 vec![
4203 Token::make_keyword("SELECT"),
4204 Token::Whitespace(Whitespace::Space),
4205 Token::Whitespace(Whitespace::SingleLineComment {
4206 prefix: "--".to_string(),
4207 comment: "'abc'".to_string(),
4208 }),
4209 ],
4210 );
4211
4212 all_dialects_where(|dialect| !dialect.requires_single_line_comment_whitespace())
4213 .tokenizes_to(
4214 "SELECT -- 'abc'",
4215 vec![
4216 Token::make_keyword("SELECT"),
4217 Token::Whitespace(Whitespace::Space),
4218 Token::Whitespace(Whitespace::SingleLineComment {
4219 prefix: "--".to_string(),
4220 comment: " 'abc'".to_string(),
4221 }),
4222 ],
4223 );
4224
4225 all_dialects_where(|dialect| !dialect.requires_single_line_comment_whitespace())
4226 .tokenizes_to(
4227 "SELECT --",
4228 vec![
4229 Token::make_keyword("SELECT"),
4230 Token::Whitespace(Whitespace::Space),
4231 Token::Whitespace(Whitespace::SingleLineComment {
4232 prefix: "--".to_string(),
4233 comment: "".to_string(),
4234 }),
4235 ],
4236 );
4237 }
4238
4239 #[test]
4240 fn test_tokenize_identifiers_numeric_prefix() {
4241 all_dialects_where(|dialect| dialect.supports_numeric_prefix())
4242 .tokenizes_to("123abc", vec![Token::make_word("123abc", None)]);
4243
4244 all_dialects_where(|dialect| dialect.supports_numeric_prefix())
4245 .tokenizes_to("12e34", vec![Token::Number("12e34".to_string(), false)]);
4246
4247 all_dialects_where(|dialect| dialect.supports_numeric_prefix()).tokenizes_to(
4248 "t.12e34",
4249 vec![
4250 Token::make_word("t", None),
4251 Token::Period,
4252 Token::make_word("12e34", None),
4253 ],
4254 );
4255
4256 all_dialects_where(|dialect| dialect.supports_numeric_prefix()).tokenizes_to(
4257 "t.1two3",
4258 vec![
4259 Token::make_word("t", None),
4260 Token::Period,
4261 Token::make_word("1two3", None),
4262 ],
4263 );
4264 }
4265
4266 #[test]
4267 fn tokenize_period_underscore() {
4268 let sql = String::from("SELECT table._col");
4269 let dialect = PostgreSqlDialect {};
4271 let tokens = Tokenizer::new(&dialect, &sql).tokenize().unwrap();
4272
4273 let expected = vec![
4274 Token::make_keyword("SELECT"),
4275 Token::Whitespace(Whitespace::Space),
4276 Token::Word(Word {
4277 value: "table".to_string(),
4278 quote_style: None,
4279 keyword: Keyword::TABLE,
4280 }),
4281 Token::Period,
4282 Token::Word(Word {
4283 value: "_col".to_string(),
4284 quote_style: None,
4285 keyword: Keyword::NoKeyword,
4286 }),
4287 ];
4288
4289 compare(expected, tokens);
4290
4291 let sql = String::from("SELECT ._123");
4292 if let Ok(tokens) = Tokenizer::new(&dialect, &sql).tokenize() {
4293 panic!("Tokenizer should have failed on {sql}, but it succeeded with {tokens:?}");
4294 }
4295
4296 let sql = String::from("SELECT ._abc");
4297 if let Ok(tokens) = Tokenizer::new(&dialect, &sql).tokenize() {
4298 panic!("Tokenizer should have failed on {sql}, but it succeeded with {tokens:?}");
4299 }
4300 }
4301
4302 #[test]
4303 fn tokenize_question_mark() {
4304 let dialect = PostgreSqlDialect {};
4305 let sql = "SELECT x ? y";
4306 let tokens = Tokenizer::new(&dialect, sql).tokenize().unwrap();
4307 compare(
4308 tokens,
4309 vec![
4310 Token::make_keyword("SELECT"),
4311 Token::Whitespace(Whitespace::Space),
4312 Token::make_word("x", None),
4313 Token::Whitespace(Whitespace::Space),
4314 Token::Question,
4315 Token::Whitespace(Whitespace::Space),
4316 Token::make_word("y", None),
4317 ],
4318 );
4319 }
4320
4321 #[test]
4322 fn tokenize_multiline_comment_with_comment_hint() {
4323 let sql = String::from("0/*! word */1");
4324
4325 let dialect = MySqlDialect {};
4326 let tokens = Tokenizer::new(&dialect, &sql).tokenize().unwrap();
4327 let expected = vec![
4328 Token::Number("0".to_string(), false),
4329 Token::Whitespace(Whitespace::Space),
4330 Token::Word(Word {
4331 value: "word".to_string(),
4332 quote_style: None,
4333 keyword: Keyword::NoKeyword,
4334 }),
4335 Token::Whitespace(Whitespace::Space),
4336 Token::Number("1".to_string(), false),
4337 ];
4338 compare(expected, tokens);
4339 }
4340
4341 #[test]
4342 fn tokenize_multiline_comment_with_comment_hint_and_version() {
4343 let sql_multi = String::from("0 /*!50110 KEY_BLOCK_SIZE = 1024*/ 1");
4344 let dialect = MySqlDialect {};
4345 let tokens = Tokenizer::new(&dialect, &sql_multi).tokenize().unwrap();
4346 let expected = vec![
4347 Token::Number("0".to_string(), false),
4348 Token::Whitespace(Whitespace::Space),
4349 Token::Whitespace(Whitespace::Space),
4350 Token::Word(Word {
4351 value: "KEY_BLOCK_SIZE".to_string(),
4352 quote_style: None,
4353 keyword: Keyword::KEY_BLOCK_SIZE,
4354 }),
4355 Token::Whitespace(Whitespace::Space),
4356 Token::Eq,
4357 Token::Whitespace(Whitespace::Space),
4358 Token::Number("1024".to_string(), false),
4359 Token::Whitespace(Whitespace::Space),
4360 Token::Number("1".to_string(), false),
4361 ];
4362 compare(expected, tokens);
4363
4364 let tokens = Tokenizer::new(&dialect, "0 /*!50110 */ 1")
4365 .tokenize()
4366 .unwrap();
4367 compare(
4368 vec![
4369 Token::Number("0".to_string(), false),
4370 Token::Whitespace(Whitespace::Space),
4371 Token::Whitespace(Whitespace::Space),
4372 Token::Whitespace(Whitespace::Space),
4373 Token::Number("1".to_string(), false),
4374 ],
4375 tokens,
4376 );
4377
4378 let tokens = Tokenizer::new(&dialect, "0 /*!*/ 1").tokenize().unwrap();
4379 compare(
4380 vec![
4381 Token::Number("0".to_string(), false),
4382 Token::Whitespace(Whitespace::Space),
4383 Token::Whitespace(Whitespace::Space),
4384 Token::Number("1".to_string(), false),
4385 ],
4386 tokens,
4387 );
4388 let tokens = Tokenizer::new(&dialect, "0 /*! */ 1").tokenize().unwrap();
4389 compare(
4390 vec![
4391 Token::Number("0".to_string(), false),
4392 Token::Whitespace(Whitespace::Space),
4393 Token::Whitespace(Whitespace::Space),
4394 Token::Whitespace(Whitespace::Space),
4395 Token::Whitespace(Whitespace::Space),
4396 Token::Whitespace(Whitespace::Space),
4397 Token::Number("1".to_string(), false),
4398 ],
4399 tokens,
4400 );
4401 }
4402}