mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-12-23 11:12:51 +00:00
refactor: Make Parser methods immutable using interior mutability
Changed all parsing methods to take '&self' instead of '\&mut self'. Mutable parser state (token index and parser state) now uses for interior mutability. This refactoring is preparation for the borrowed tokenizer work. When holding borrowed tokens from the parser (with lifetime tied to '\&self'), we cannot call methods requiring '\&mut self' due to Rust's borrowing rules. Using interior mutability resolves this conflict by allowing state mutations through shared references.
This commit is contained in:
parent
b098976cab
commit
650b1ca18f
13 changed files with 658 additions and 716 deletions
|
|
@ -2790,7 +2790,7 @@ impl fmt::Display for Declare {
|
|||
}
|
||||
|
||||
/// Sql options of a `CREATE TABLE` statement.
|
||||
#[derive(Debug, Default, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
|
||||
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Default)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
|
||||
pub enum CreateTableOptions {
|
||||
|
|
|
|||
|
|
@ -2407,7 +2407,7 @@ pub mod tests {
|
|||
#[test]
|
||||
fn test_join() {
|
||||
let dialect = &GenericDialect;
|
||||
let mut test = SpanTest::new(
|
||||
let test = SpanTest::new(
|
||||
dialect,
|
||||
"SELECT id, name FROM users LEFT JOIN companies ON users.company_id = companies.id",
|
||||
);
|
||||
|
|
@ -2432,7 +2432,7 @@ pub mod tests {
|
|||
#[test]
|
||||
pub fn test_union() {
|
||||
let dialect = &GenericDialect;
|
||||
let mut test = SpanTest::new(
|
||||
let test = SpanTest::new(
|
||||
dialect,
|
||||
"SELECT a FROM postgres.public.source UNION SELECT a FROM postgres.public.source",
|
||||
);
|
||||
|
|
@ -2449,7 +2449,7 @@ pub mod tests {
|
|||
#[test]
|
||||
pub fn test_subquery() {
|
||||
let dialect = &GenericDialect;
|
||||
let mut test = SpanTest::new(
|
||||
let test = SpanTest::new(
|
||||
dialect,
|
||||
"SELECT a FROM (SELECT a FROM postgres.public.source) AS b",
|
||||
);
|
||||
|
|
@ -2474,7 +2474,7 @@ pub mod tests {
|
|||
#[test]
|
||||
pub fn test_cte() {
|
||||
let dialect = &GenericDialect;
|
||||
let mut test = SpanTest::new(dialect, "WITH cte_outer AS (SELECT a FROM postgres.public.source), cte_ignored AS (SELECT a FROM cte_outer), cte_inner AS (SELECT a FROM cte_outer) SELECT a FROM cte_inner");
|
||||
let test = SpanTest::new(dialect, "WITH cte_outer AS (SELECT a FROM postgres.public.source), cte_ignored AS (SELECT a FROM cte_outer), cte_inner AS (SELECT a FROM cte_outer) SELECT a FROM cte_inner");
|
||||
|
||||
let query = test.0.parse_query().unwrap();
|
||||
|
||||
|
|
@ -2486,7 +2486,7 @@ pub mod tests {
|
|||
#[test]
|
||||
pub fn test_snowflake_lateral_flatten() {
|
||||
let dialect = &SnowflakeDialect;
|
||||
let mut test = SpanTest::new(dialect, "SELECT FLATTENED.VALUE:field::TEXT AS FIELD FROM SNOWFLAKE.SCHEMA.SOURCE AS S, LATERAL FLATTEN(INPUT => S.JSON_ARRAY) AS FLATTENED");
|
||||
let test = SpanTest::new(dialect, "SELECT FLATTENED.VALUE:field::TEXT AS FIELD FROM SNOWFLAKE.SCHEMA.SOURCE AS S, LATERAL FLATTEN(INPUT => S.JSON_ARRAY) AS FLATTENED");
|
||||
|
||||
let query = test.0.parse_select().unwrap();
|
||||
|
||||
|
|
@ -2498,7 +2498,7 @@ pub mod tests {
|
|||
#[test]
|
||||
pub fn test_wildcard_from_cte() {
|
||||
let dialect = &GenericDialect;
|
||||
let mut test = SpanTest::new(
|
||||
let test = SpanTest::new(
|
||||
dialect,
|
||||
"WITH cte AS (SELECT a FROM postgres.public.source) SELECT cte.* FROM cte",
|
||||
);
|
||||
|
|
@ -2524,7 +2524,7 @@ pub mod tests {
|
|||
#[test]
|
||||
fn test_case_expr_span() {
|
||||
let dialect = &GenericDialect;
|
||||
let mut test = SpanTest::new(dialect, "CASE 1 WHEN 2 THEN 3 ELSE 4 END");
|
||||
let test = SpanTest::new(dialect, "CASE 1 WHEN 2 THEN 3 ELSE 4 END");
|
||||
let expr = test.0.parse_expr().unwrap();
|
||||
let expr_span = expr.span();
|
||||
assert_eq!(
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ const RESERVED_FOR_COLUMN_ALIAS: &[Keyword] = &[
|
|||
pub struct BigQueryDialect;
|
||||
|
||||
impl Dialect for BigQueryDialect {
|
||||
fn parse_statement(&self, parser: &mut Parser) -> Option<Result<Statement, ParserError>> {
|
||||
fn parse_statement(&self, parser: &Parser) -> Option<Result<Statement, ParserError>> {
|
||||
if parser.parse_keyword(Keyword::BEGIN) {
|
||||
if parser.peek_keyword(Keyword::TRANSACTION)
|
||||
|| parser.peek_token_ref().token == Token::SemiColon
|
||||
|
|
@ -145,7 +145,7 @@ impl Dialect for BigQueryDialect {
|
|||
true
|
||||
}
|
||||
|
||||
fn is_column_alias(&self, kw: &Keyword, _parser: &mut Parser) -> bool {
|
||||
fn is_column_alias(&self, kw: &Keyword, _parser: &Parser) -> bool {
|
||||
!RESERVED_FOR_COLUMN_ALIAS.contains(kw)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -466,7 +466,7 @@ pub trait Dialect: Debug + Any {
|
|||
}
|
||||
|
||||
/// Dialect-specific prefix parser override
|
||||
fn parse_prefix(&self, _parser: &mut Parser) -> Option<Result<Expr, ParserError>> {
|
||||
fn parse_prefix(&self, _parser: &Parser) -> Option<Result<Expr, ParserError>> {
|
||||
// return None to fall back to the default behavior
|
||||
None
|
||||
}
|
||||
|
|
@ -615,7 +615,7 @@ pub trait Dialect: Debug + Any {
|
|||
/// If `None` is returned, falls back to the default behavior.
|
||||
fn parse_infix(
|
||||
&self,
|
||||
_parser: &mut Parser,
|
||||
_parser: &Parser,
|
||||
_expr: &Expr,
|
||||
_precedence: u8,
|
||||
) -> Option<Result<Expr, ParserError>> {
|
||||
|
|
@ -778,7 +778,7 @@ pub trait Dialect: Debug + Any {
|
|||
/// This method is called to parse the next statement.
|
||||
///
|
||||
/// If `None` is returned, falls back to the default behavior.
|
||||
fn parse_statement(&self, _parser: &mut Parser) -> Option<Result<Statement, ParserError>> {
|
||||
fn parse_statement(&self, _parser: &Parser) -> Option<Result<Statement, ParserError>> {
|
||||
// return None to fall back to the default behavior
|
||||
None
|
||||
}
|
||||
|
|
@ -790,7 +790,7 @@ pub trait Dialect: Debug + Any {
|
|||
/// If `None` is returned, falls back to the default behavior.
|
||||
fn parse_column_option(
|
||||
&self,
|
||||
_parser: &mut Parser,
|
||||
_parser: &Parser,
|
||||
) -> Result<Option<Result<Option<ColumnOption>, ParserError>>, ParserError> {
|
||||
// return None to fall back to the default behavior
|
||||
Ok(None)
|
||||
|
|
@ -1021,33 +1021,33 @@ pub trait Dialect: Debug + Any {
|
|||
|
||||
/// Returns true if the specified keyword should be parsed as a column identifier.
|
||||
/// See [keywords::RESERVED_FOR_COLUMN_ALIAS]
|
||||
fn is_column_alias(&self, kw: &Keyword, _parser: &mut Parser) -> bool {
|
||||
fn is_column_alias(&self, kw: &Keyword, _parser: &Parser) -> bool {
|
||||
!keywords::RESERVED_FOR_COLUMN_ALIAS.contains(kw)
|
||||
}
|
||||
|
||||
/// Returns true if the specified keyword should be parsed as a select item alias.
|
||||
/// When explicit is true, the keyword is preceded by an `AS` word. Parser is provided
|
||||
/// to enable looking ahead if needed.
|
||||
fn is_select_item_alias(&self, explicit: bool, kw: &Keyword, parser: &mut Parser) -> bool {
|
||||
fn is_select_item_alias(&self, explicit: bool, kw: &Keyword, parser: &Parser) -> bool {
|
||||
explicit || self.is_column_alias(kw, parser)
|
||||
}
|
||||
|
||||
/// Returns true if the specified keyword should be parsed as a table factor identifier.
|
||||
/// See [keywords::RESERVED_FOR_TABLE_FACTOR]
|
||||
fn is_table_factor(&self, kw: &Keyword, _parser: &mut Parser) -> bool {
|
||||
fn is_table_factor(&self, kw: &Keyword, _parser: &Parser) -> bool {
|
||||
!keywords::RESERVED_FOR_TABLE_FACTOR.contains(kw)
|
||||
}
|
||||
|
||||
/// Returns true if the specified keyword should be parsed as a table factor alias.
|
||||
/// See [keywords::RESERVED_FOR_TABLE_ALIAS]
|
||||
fn is_table_alias(&self, kw: &Keyword, _parser: &mut Parser) -> bool {
|
||||
fn is_table_alias(&self, kw: &Keyword, _parser: &Parser) -> bool {
|
||||
!keywords::RESERVED_FOR_TABLE_ALIAS.contains(kw)
|
||||
}
|
||||
|
||||
/// Returns true if the specified keyword should be parsed as a table factor alias.
|
||||
/// When explicit is true, the keyword is preceded by an `AS` word. Parser is provided
|
||||
/// to enable looking ahead if needed.
|
||||
fn is_table_factor_alias(&self, explicit: bool, kw: &Keyword, parser: &mut Parser) -> bool {
|
||||
fn is_table_factor_alias(&self, explicit: bool, kw: &Keyword, parser: &Parser) -> bool {
|
||||
explicit || self.is_table_alias(kw, parser)
|
||||
}
|
||||
|
||||
|
|
@ -1400,14 +1400,14 @@ mod tests {
|
|||
|
||||
fn parse_prefix(
|
||||
&self,
|
||||
parser: &mut sqlparser::parser::Parser,
|
||||
parser: &sqlparser::parser::Parser,
|
||||
) -> Option<Result<Expr, sqlparser::parser::ParserError>> {
|
||||
self.0.parse_prefix(parser)
|
||||
}
|
||||
|
||||
fn parse_infix(
|
||||
&self,
|
||||
parser: &mut sqlparser::parser::Parser,
|
||||
parser: &sqlparser::parser::Parser,
|
||||
expr: &Expr,
|
||||
precedence: u8,
|
||||
) -> Option<Result<Expr, sqlparser::parser::ParserError>> {
|
||||
|
|
@ -1423,7 +1423,7 @@ mod tests {
|
|||
|
||||
fn parse_statement(
|
||||
&self,
|
||||
parser: &mut sqlparser::parser::Parser,
|
||||
parser: &sqlparser::parser::Parser,
|
||||
) -> Option<Result<Statement, sqlparser::parser::ParserError>> {
|
||||
self.0.parse_statement(parser)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -128,11 +128,11 @@ impl Dialect for MsSqlDialect {
|
|||
&[GranteesType::Public]
|
||||
}
|
||||
|
||||
fn is_column_alias(&self, kw: &Keyword, _parser: &mut Parser) -> bool {
|
||||
fn is_column_alias(&self, kw: &Keyword, _parser: &Parser) -> bool {
|
||||
!keywords::RESERVED_FOR_COLUMN_ALIAS.contains(kw) && !RESERVED_FOR_COLUMN_ALIAS.contains(kw)
|
||||
}
|
||||
|
||||
fn parse_statement(&self, parser: &mut Parser) -> Option<Result<Statement, ParserError>> {
|
||||
fn parse_statement(&self, parser: &Parser) -> Option<Result<Statement, ParserError>> {
|
||||
if parser.peek_keyword(Keyword::IF) {
|
||||
Some(self.parse_if_stmt(parser))
|
||||
} else if parser.parse_keywords(&[Keyword::CREATE, Keyword::TRIGGER]) {
|
||||
|
|
@ -157,7 +157,7 @@ impl MsSqlDialect {
|
|||
/// [ ELSE
|
||||
/// { sql_statement | statement_block } ]
|
||||
/// ```
|
||||
fn parse_if_stmt(&self, parser: &mut Parser) -> Result<Statement, ParserError> {
|
||||
fn parse_if_stmt(&self, parser: &Parser) -> Result<Statement, ParserError> {
|
||||
let if_token = parser.expect_keyword(Keyword::IF)?;
|
||||
|
||||
let condition = parser.parse_expr()?;
|
||||
|
|
@ -240,7 +240,7 @@ impl MsSqlDialect {
|
|||
/// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-trigger-transact-sql
|
||||
fn parse_create_trigger(
|
||||
&self,
|
||||
parser: &mut Parser,
|
||||
parser: &Parser,
|
||||
or_alter: bool,
|
||||
) -> Result<Statement, ParserError> {
|
||||
let name = parser.parse_object_name(false)?;
|
||||
|
|
@ -279,7 +279,7 @@ impl MsSqlDialect {
|
|||
/// Stops parsing when reaching EOF or the given keyword.
|
||||
fn parse_statement_list(
|
||||
&self,
|
||||
parser: &mut Parser,
|
||||
parser: &Parser,
|
||||
terminal_keyword: Option<Keyword>,
|
||||
) -> Result<Vec<Statement>, ParserError> {
|
||||
let mut stmts = Vec::new();
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ impl Dialect for MySqlDialect {
|
|||
|
||||
fn parse_infix(
|
||||
&self,
|
||||
parser: &mut crate::parser::Parser,
|
||||
parser: &crate::parser::Parser,
|
||||
expr: &crate::ast::Expr,
|
||||
_precedence: u8,
|
||||
) -> Option<Result<crate::ast::Expr, ParserError>> {
|
||||
|
|
@ -102,7 +102,7 @@ impl Dialect for MySqlDialect {
|
|||
}
|
||||
}
|
||||
|
||||
fn parse_statement(&self, parser: &mut Parser) -> Option<Result<Statement, ParserError>> {
|
||||
fn parse_statement(&self, parser: &Parser) -> Option<Result<Statement, ParserError>> {
|
||||
if parser.parse_keywords(&[Keyword::LOCK, Keyword::TABLES]) {
|
||||
Some(parse_lock_tables(parser))
|
||||
} else if parser.parse_keywords(&[Keyword::UNLOCK, Keyword::TABLES]) {
|
||||
|
|
@ -134,7 +134,7 @@ impl Dialect for MySqlDialect {
|
|||
true
|
||||
}
|
||||
|
||||
fn is_table_factor_alias(&self, explicit: bool, kw: &Keyword, _parser: &mut Parser) -> bool {
|
||||
fn is_table_factor_alias(&self, explicit: bool, kw: &Keyword, _parser: &Parser) -> bool {
|
||||
explicit
|
||||
|| (!keywords::RESERVED_FOR_TABLE_ALIAS.contains(kw)
|
||||
&& !RESERVED_FOR_TABLE_ALIAS_MYSQL.contains(kw))
|
||||
|
|
@ -171,13 +171,13 @@ impl Dialect for MySqlDialect {
|
|||
|
||||
/// `LOCK TABLES`
|
||||
/// <https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html>
|
||||
fn parse_lock_tables(parser: &mut Parser) -> Result<Statement, ParserError> {
|
||||
fn parse_lock_tables(parser: &Parser) -> Result<Statement, ParserError> {
|
||||
let tables = parser.parse_comma_separated(parse_lock_table)?;
|
||||
Ok(Statement::LockTables { tables })
|
||||
}
|
||||
|
||||
// tbl_name [[AS] alias] lock_type
|
||||
fn parse_lock_table(parser: &mut Parser) -> Result<LockTable, ParserError> {
|
||||
fn parse_lock_table(parser: &Parser) -> Result<LockTable, ParserError> {
|
||||
let table = parser.parse_identifier()?;
|
||||
let alias =
|
||||
parser.parse_optional_alias(&[Keyword::READ, Keyword::WRITE, Keyword::LOW_PRIORITY])?;
|
||||
|
|
@ -191,7 +191,7 @@ fn parse_lock_table(parser: &mut Parser) -> Result<LockTable, ParserError> {
|
|||
}
|
||||
|
||||
// READ [LOCAL] | [LOW_PRIORITY] WRITE
|
||||
fn parse_lock_tables_type(parser: &mut Parser) -> Result<LockTableType, ParserError> {
|
||||
fn parse_lock_tables_type(parser: &Parser) -> Result<LockTableType, ParserError> {
|
||||
if parser.parse_keyword(Keyword::READ) {
|
||||
if parser.parse_keyword(Keyword::LOCAL) {
|
||||
Ok(LockTableType::Read { local: true })
|
||||
|
|
@ -211,6 +211,6 @@ fn parse_lock_tables_type(parser: &mut Parser) -> Result<LockTableType, ParserEr
|
|||
|
||||
/// UNLOCK TABLES
|
||||
/// <https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html>
|
||||
fn parse_unlock_tables(_parser: &mut Parser) -> Result<Statement, ParserError> {
|
||||
fn parse_unlock_tables(_parser: &Parser) -> Result<Statement, ParserError> {
|
||||
Ok(Statement::UnlockTables)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -211,7 +211,7 @@ impl Dialect for SnowflakeDialect {
|
|||
true
|
||||
}
|
||||
|
||||
fn parse_statement(&self, parser: &mut Parser) -> Option<Result<Statement, ParserError>> {
|
||||
fn parse_statement(&self, parser: &Parser) -> Option<Result<Statement, ParserError>> {
|
||||
if parser.parse_keyword(Keyword::BEGIN) {
|
||||
return Some(parser.parse_begin_exception_end());
|
||||
}
|
||||
|
|
@ -318,7 +318,7 @@ impl Dialect for SnowflakeDialect {
|
|||
|
||||
fn parse_column_option(
|
||||
&self,
|
||||
parser: &mut Parser,
|
||||
parser: &Parser,
|
||||
) -> Result<Option<Result<Option<ColumnOption>, ParserError>>, ParserError> {
|
||||
parser.maybe_parse(|parser| {
|
||||
let with = parser.parse_keyword(Keyword::WITH);
|
||||
|
|
@ -391,7 +391,7 @@ impl Dialect for SnowflakeDialect {
|
|||
true
|
||||
}
|
||||
|
||||
fn is_column_alias(&self, kw: &Keyword, parser: &mut Parser) -> bool {
|
||||
fn is_column_alias(&self, kw: &Keyword, parser: &Parser) -> bool {
|
||||
match kw {
|
||||
// The following keywords can be considered an alias as long as
|
||||
// they are not followed by other tokens that may change their meaning
|
||||
|
|
@ -437,7 +437,7 @@ impl Dialect for SnowflakeDialect {
|
|||
}
|
||||
}
|
||||
|
||||
fn is_table_alias(&self, kw: &Keyword, parser: &mut Parser) -> bool {
|
||||
fn is_table_alias(&self, kw: &Keyword, parser: &Parser) -> bool {
|
||||
match kw {
|
||||
// The following keywords can be considered an alias as long as
|
||||
// they are not followed by other tokens that may change their meaning
|
||||
|
|
@ -521,7 +521,7 @@ impl Dialect for SnowflakeDialect {
|
|||
}
|
||||
}
|
||||
|
||||
fn is_table_factor(&self, kw: &Keyword, parser: &mut Parser) -> bool {
|
||||
fn is_table_factor(&self, kw: &Keyword, parser: &Parser) -> bool {
|
||||
match kw {
|
||||
Keyword::LIMIT if peek_for_limit_options(parser) => false,
|
||||
// Table function
|
||||
|
|
@ -591,7 +591,7 @@ fn peek_for_limit_options(parser: &Parser) -> bool {
|
|||
}
|
||||
}
|
||||
|
||||
fn parse_file_staging_command(kw: Keyword, parser: &mut Parser) -> Result<Statement, ParserError> {
|
||||
fn parse_file_staging_command(kw: Keyword, parser: &Parser) -> Result<Statement, ParserError> {
|
||||
let stage = parse_snowflake_stage_name(parser)?;
|
||||
let pattern = if parser.parse_keyword(Keyword::PATTERN) {
|
||||
parser.expect_token(&Token::Eq)?;
|
||||
|
|
@ -613,7 +613,7 @@ fn parse_file_staging_command(kw: Keyword, parser: &mut Parser) -> Result<Statem
|
|||
|
||||
/// Parse snowflake alter dynamic table.
|
||||
/// <https://docs.snowflake.com/en/sql-reference/sql/alter-table>
|
||||
fn parse_alter_dynamic_table(parser: &mut Parser) -> Result<Statement, ParserError> {
|
||||
fn parse_alter_dynamic_table(parser: &Parser) -> Result<Statement, ParserError> {
|
||||
// Use parse_object_name(true) to support IDENTIFIER() function
|
||||
let table_name = parser.parse_object_name(true)?;
|
||||
|
||||
|
|
@ -651,7 +651,7 @@ fn parse_alter_dynamic_table(parser: &mut Parser) -> Result<Statement, ParserErr
|
|||
|
||||
/// Parse snowflake alter session.
|
||||
/// <https://docs.snowflake.com/en/sql-reference/sql/alter-session>
|
||||
fn parse_alter_session(parser: &mut Parser, set: bool) -> Result<Statement, ParserError> {
|
||||
fn parse_alter_session(parser: &Parser, set: bool) -> Result<Statement, ParserError> {
|
||||
let session_options = parse_session_options(parser, set)?;
|
||||
Ok(Statement::AlterSession {
|
||||
set,
|
||||
|
|
@ -674,7 +674,7 @@ pub fn parse_create_table(
|
|||
transient: bool,
|
||||
iceberg: bool,
|
||||
dynamic: bool,
|
||||
parser: &mut Parser,
|
||||
parser: &Parser,
|
||||
) -> Result<Statement, ParserError> {
|
||||
let if_not_exists = parser.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
|
||||
let table_name = parser.parse_object_name(false)?;
|
||||
|
|
@ -912,7 +912,7 @@ pub fn parse_create_table(
|
|||
pub fn parse_create_database(
|
||||
or_replace: bool,
|
||||
transient: bool,
|
||||
parser: &mut Parser,
|
||||
parser: &Parser,
|
||||
) -> Result<Statement, ParserError> {
|
||||
let if_not_exists = parser.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
|
||||
let name = parser.parse_object_name(false)?;
|
||||
|
|
@ -1017,7 +1017,7 @@ pub fn parse_create_database(
|
|||
}
|
||||
|
||||
pub fn parse_storage_serialization_policy(
|
||||
parser: &mut Parser,
|
||||
parser: &Parser,
|
||||
) -> Result<StorageSerializationPolicy, ParserError> {
|
||||
let next_token = parser.next_token();
|
||||
match &next_token.token {
|
||||
|
|
@ -1033,7 +1033,7 @@ pub fn parse_storage_serialization_policy(
|
|||
pub fn parse_create_stage(
|
||||
or_replace: bool,
|
||||
temporary: bool,
|
||||
parser: &mut Parser,
|
||||
parser: &Parser,
|
||||
) -> Result<Statement, ParserError> {
|
||||
//[ IF NOT EXISTS ]
|
||||
let if_not_exists = parser.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
|
||||
|
|
@ -1092,7 +1092,7 @@ pub fn parse_create_stage(
|
|||
})
|
||||
}
|
||||
|
||||
pub fn parse_stage_name_identifier(parser: &mut Parser) -> Result<Ident, ParserError> {
|
||||
pub fn parse_stage_name_identifier(parser: &Parser) -> Result<Ident, ParserError> {
|
||||
let mut ident = String::new();
|
||||
while let Some(next_token) = parser.next_token_no_skip() {
|
||||
match &next_token.token {
|
||||
|
|
@ -1119,7 +1119,7 @@ pub fn parse_stage_name_identifier(parser: &mut Parser) -> Result<Ident, ParserE
|
|||
Ok(Ident::new(ident))
|
||||
}
|
||||
|
||||
pub fn parse_snowflake_stage_name(parser: &mut Parser) -> Result<ObjectName, ParserError> {
|
||||
pub fn parse_snowflake_stage_name(parser: &Parser) -> Result<ObjectName, ParserError> {
|
||||
match parser.next_token().token {
|
||||
Token::AtSign => {
|
||||
parser.prev_token();
|
||||
|
|
@ -1141,7 +1141,7 @@ pub fn parse_snowflake_stage_name(parser: &mut Parser) -> Result<ObjectName, Par
|
|||
|
||||
/// Parses a `COPY INTO` statement. Snowflake has two variants, `COPY INTO <table>`
|
||||
/// and `COPY INTO <location>` which have different syntax.
|
||||
pub fn parse_copy_into(parser: &mut Parser) -> Result<Statement, ParserError> {
|
||||
pub fn parse_copy_into(parser: &Parser) -> Result<Statement, ParserError> {
|
||||
let kind = match parser.peek_token().token {
|
||||
// Indicates an internal stage
|
||||
Token::AtSign => CopyIntoSnowflakeKind::Location,
|
||||
|
|
@ -1303,7 +1303,7 @@ pub fn parse_copy_into(parser: &mut Parser) -> Result<Statement, ParserError> {
|
|||
}
|
||||
|
||||
fn parse_select_items_for_data_load(
|
||||
parser: &mut Parser,
|
||||
parser: &Parser,
|
||||
) -> Result<Option<Vec<StageLoadSelectItemKind>>, ParserError> {
|
||||
let mut select_items: Vec<StageLoadSelectItemKind> = vec![];
|
||||
loop {
|
||||
|
|
@ -1324,9 +1324,7 @@ fn parse_select_items_for_data_load(
|
|||
Ok(Some(select_items))
|
||||
}
|
||||
|
||||
fn parse_select_item_for_data_load(
|
||||
parser: &mut Parser,
|
||||
) -> Result<StageLoadSelectItem, ParserError> {
|
||||
fn parse_select_item_for_data_load(parser: &Parser) -> Result<StageLoadSelectItem, ParserError> {
|
||||
let mut alias: Option<Ident> = None;
|
||||
let mut file_col_num: i32 = 0;
|
||||
let mut element: Option<Ident> = None;
|
||||
|
|
@ -1393,7 +1391,7 @@ fn parse_select_item_for_data_load(
|
|||
})
|
||||
}
|
||||
|
||||
fn parse_stage_params(parser: &mut Parser) -> Result<StageParamsObject, ParserError> {
|
||||
fn parse_stage_params(parser: &Parser) -> Result<StageParamsObject, ParserError> {
|
||||
let (mut url, mut storage_integration, mut endpoint) = (None, None, None);
|
||||
let mut encryption: KeyValueOptions = KeyValueOptions {
|
||||
options: vec![],
|
||||
|
|
@ -1459,10 +1457,7 @@ fn parse_stage_params(parser: &mut Parser) -> Result<StageParamsObject, ParserEr
|
|||
/// ABORT_DETACHED_QUERY = { TRUE | FALSE }
|
||||
/// [ ACTIVE_PYTHON_PROFILER = { 'LINE' | 'MEMORY' } ]
|
||||
/// [ BINARY_INPUT_FORMAT = '\<string\>' ]
|
||||
fn parse_session_options(
|
||||
parser: &mut Parser,
|
||||
set: bool,
|
||||
) -> Result<Vec<KeyValueOption>, ParserError> {
|
||||
fn parse_session_options(parser: &Parser, set: bool) -> Result<Vec<KeyValueOption>, ParserError> {
|
||||
let mut options: Vec<KeyValueOption> = Vec::new();
|
||||
let empty = String::new;
|
||||
loop {
|
||||
|
|
@ -1505,7 +1500,7 @@ fn parse_session_options(
|
|||
/// [ (seed , increment) | START num INCREMENT num ] [ ORDER | NOORDER ]
|
||||
/// ```
|
||||
/// [Snowflake]: https://docs.snowflake.com/en/sql-reference/sql/create-table
|
||||
fn parse_identity_property(parser: &mut Parser) -> Result<IdentityProperty, ParserError> {
|
||||
fn parse_identity_property(parser: &Parser) -> Result<IdentityProperty, ParserError> {
|
||||
let parameters = if parser.consume_token(&Token::LParen) {
|
||||
let seed = parser.parse_number()?;
|
||||
parser.expect_token(&Token::Comma)?;
|
||||
|
|
@ -1541,7 +1536,7 @@ fn parse_identity_property(parser: &mut Parser) -> Result<IdentityProperty, Pars
|
|||
/// ```
|
||||
/// [Snowflake]: https://docs.snowflake.com/en/sql-reference/sql/create-table
|
||||
fn parse_column_policy_property(
|
||||
parser: &mut Parser,
|
||||
parser: &Parser,
|
||||
with: bool,
|
||||
) -> Result<ColumnPolicyProperty, ParserError> {
|
||||
let policy_name = parser.parse_object_name(false)?;
|
||||
|
|
@ -1567,7 +1562,7 @@ fn parse_column_policy_property(
|
|||
/// ( <tag_name> = '<tag_value>' [ , <tag_name> = '<tag_value>' , ... ] )
|
||||
/// ```
|
||||
/// [Snowflake]: https://docs.snowflake.com/en/sql-reference/sql/create-table
|
||||
fn parse_column_tags(parser: &mut Parser, with: bool) -> Result<TagsColumnOption, ParserError> {
|
||||
fn parse_column_tags(parser: &Parser, with: bool) -> Result<TagsColumnOption, ParserError> {
|
||||
parser.expect_token(&Token::LParen)?;
|
||||
let tags = parser.parse_comma_separated(Parser::parse_tag)?;
|
||||
parser.expect_token(&Token::RParen)?;
|
||||
|
|
@ -1577,7 +1572,7 @@ fn parse_column_tags(parser: &mut Parser, with: bool) -> Result<TagsColumnOption
|
|||
|
||||
/// Parse snowflake show objects.
|
||||
/// <https://docs.snowflake.com/en/sql-reference/sql/show-objects>
|
||||
fn parse_show_objects(terse: bool, parser: &mut Parser) -> Result<Statement, ParserError> {
|
||||
fn parse_show_objects(terse: bool, parser: &Parser) -> Result<Statement, ParserError> {
|
||||
let show_options = parser.parse_show_stmt_options()?;
|
||||
Ok(Statement::ShowObjects(ShowObjects {
|
||||
terse,
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ impl Dialect for SQLiteDialect {
|
|||
self.is_identifier_start(ch) || ch.is_ascii_digit()
|
||||
}
|
||||
|
||||
fn parse_statement(&self, parser: &mut Parser) -> Option<Result<Statement, ParserError>> {
|
||||
fn parse_statement(&self, parser: &Parser) -> Option<Result<Statement, ParserError>> {
|
||||
if parser.parse_keyword(Keyword::REPLACE) {
|
||||
parser.prev_token();
|
||||
Some(parser.parse_insert(parser.get_current_token().clone()))
|
||||
|
|
@ -76,7 +76,7 @@ impl Dialect for SQLiteDialect {
|
|||
|
||||
fn parse_infix(
|
||||
&self,
|
||||
parser: &mut crate::parser::Parser,
|
||||
parser: &crate::parser::Parser,
|
||||
expr: &crate::ast::Expr,
|
||||
_precedence: u8,
|
||||
) -> Option<Result<crate::ast::Expr, ParserError>> {
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ use crate::{
|
|||
};
|
||||
|
||||
impl Parser<'_> {
|
||||
pub fn parse_alter_role(&mut self) -> Result<Statement, ParserError> {
|
||||
pub fn parse_alter_role(&self) -> Result<Statement, ParserError> {
|
||||
if dialect_of!(self is PostgreSqlDialect) {
|
||||
return self.parse_pg_alter_role();
|
||||
} else if dialect_of!(self is MsSqlDialect) {
|
||||
|
|
@ -53,7 +53,7 @@ impl Parser<'_> {
|
|||
/// ```
|
||||
///
|
||||
/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-alterpolicy.html)
|
||||
pub fn parse_alter_policy(&mut self) -> Result<Statement, ParserError> {
|
||||
pub fn parse_alter_policy(&self) -> Result<Statement, ParserError> {
|
||||
let name = self.parse_identifier()?;
|
||||
self.expect_keyword_is(Keyword::ON)?;
|
||||
let table_name = self.parse_object_name(false)?;
|
||||
|
|
@ -110,7 +110,7 @@ impl Parser<'_> {
|
|||
///
|
||||
/// ALTER CONNECTOR connector_name SET OWNER [USER|ROLE] user_or_role;
|
||||
/// ```
|
||||
pub fn parse_alter_connector(&mut self) -> Result<Statement, ParserError> {
|
||||
pub fn parse_alter_connector(&self) -> Result<Statement, ParserError> {
|
||||
let name = self.parse_identifier()?;
|
||||
self.expect_keyword_is(Keyword::SET)?;
|
||||
|
||||
|
|
@ -147,7 +147,7 @@ impl Parser<'_> {
|
|||
/// ```sql
|
||||
/// ALTER USER [ IF EXISTS ] [ <name> ] [ OPTIONS ]
|
||||
/// ```
|
||||
pub fn parse_alter_user(&mut self) -> Result<Statement, ParserError> {
|
||||
pub fn parse_alter_user(&self) -> Result<Statement, ParserError> {
|
||||
let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
|
||||
let name = self.parse_identifier()?;
|
||||
let rename_to = if self.parse_keywords(&[Keyword::RENAME, Keyword::TO]) {
|
||||
|
|
@ -314,7 +314,7 @@ impl Parser<'_> {
|
|||
}))
|
||||
}
|
||||
|
||||
fn parse_mfa_method(&mut self) -> Result<MfaMethodKind, ParserError> {
|
||||
fn parse_mfa_method(&self) -> Result<MfaMethodKind, ParserError> {
|
||||
if self.parse_keyword(Keyword::PASSKEY) {
|
||||
Ok(MfaMethodKind::PassKey)
|
||||
} else if self.parse_keyword(Keyword::TOTP) {
|
||||
|
|
@ -326,7 +326,7 @@ impl Parser<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
fn parse_mssql_alter_role(&mut self) -> Result<Statement, ParserError> {
|
||||
fn parse_mssql_alter_role(&self) -> Result<Statement, ParserError> {
|
||||
let role_name = self.parse_identifier()?;
|
||||
|
||||
let operation = if self.parse_keywords(&[Keyword::ADD, Keyword::MEMBER]) {
|
||||
|
|
@ -352,7 +352,7 @@ impl Parser<'_> {
|
|||
})
|
||||
}
|
||||
|
||||
fn parse_pg_alter_role(&mut self) -> Result<Statement, ParserError> {
|
||||
fn parse_pg_alter_role(&self) -> Result<Statement, ParserError> {
|
||||
let role_name = self.parse_identifier()?;
|
||||
|
||||
// [ IN DATABASE _`database_name`_ ]
|
||||
|
|
@ -436,7 +436,7 @@ impl Parser<'_> {
|
|||
})
|
||||
}
|
||||
|
||||
fn parse_pg_role_option(&mut self) -> Result<RoleOption, ParserError> {
|
||||
fn parse_pg_role_option(&self) -> Result<RoleOption, ParserError> {
|
||||
let option = match self.parse_one_of_keywords(&[
|
||||
Keyword::BYPASSRLS,
|
||||
Keyword::NOBYPASSRLS,
|
||||
|
|
|
|||
1189
src/parser/mod.rs
1189
src/parser/mod.rs
File diff suppressed because it is too large
Load diff
|
|
@ -311,8 +311,7 @@ fn parse_insert_default_values() {
|
|||
fn parse_insert_select_returning() {
|
||||
// Dialects that support `RETURNING` as a column identifier do
|
||||
// not support this syntax.
|
||||
let dialects =
|
||||
all_dialects_where(|d| !d.is_column_alias(&Keyword::RETURNING, &mut Parser::new(d)));
|
||||
let dialects = all_dialects_where(|d| !d.is_column_alias(&Keyword::RETURNING, &Parser::new(d)));
|
||||
|
||||
dialects.verified_stmt("INSERT INTO t SELECT 1 RETURNING 2");
|
||||
let stmt = dialects.verified_stmt("INSERT INTO t SELECT x RETURNING x AS y");
|
||||
|
|
@ -5655,7 +5654,7 @@ fn parse_named_window_functions() {
|
|||
WINDOW w AS (PARTITION BY x), win AS (ORDER BY y)";
|
||||
supported_dialects.verified_stmt(sql);
|
||||
|
||||
let select = all_dialects_except(|d| d.is_table_alias(&Keyword::WINDOW, &mut Parser::new(d)))
|
||||
let select = all_dialects_except(|d| d.is_table_alias(&Keyword::WINDOW, &Parser::new(d)))
|
||||
.verified_only_select(sql);
|
||||
|
||||
const EXPECTED_PROJ_QTY: usize = 2;
|
||||
|
|
@ -5686,7 +5685,7 @@ fn parse_named_window_functions() {
|
|||
|
||||
#[test]
|
||||
fn parse_window_clause() {
|
||||
let dialects = all_dialects_except(|d| d.is_table_alias(&Keyword::WINDOW, &mut Parser::new(d)));
|
||||
let dialects = all_dialects_except(|d| d.is_table_alias(&Keyword::WINDOW, &Parser::new(d)));
|
||||
let sql = "SELECT * \
|
||||
FROM mytable \
|
||||
WINDOW \
|
||||
|
|
@ -5705,7 +5704,7 @@ fn parse_window_clause() {
|
|||
let dialects = all_dialects_except(|d| {
|
||||
d.is::<BigQueryDialect>()
|
||||
|| d.is::<GenericDialect>()
|
||||
|| d.is_table_alias(&Keyword::WINDOW, &mut Parser::new(d))
|
||||
|| d.is_table_alias(&Keyword::WINDOW, &Parser::new(d))
|
||||
});
|
||||
let res = dialects.parse_sql_statements(sql);
|
||||
assert_eq!(
|
||||
|
|
@ -5716,7 +5715,7 @@ fn parse_window_clause() {
|
|||
|
||||
#[test]
|
||||
fn test_parse_named_window() {
|
||||
let dialects = all_dialects_except(|d| d.is_table_alias(&Keyword::WINDOW, &mut Parser::new(d)));
|
||||
let dialects = all_dialects_except(|d| d.is_table_alias(&Keyword::WINDOW, &Parser::new(d)));
|
||||
let sql = "SELECT \
|
||||
MIN(c12) OVER window1 AS min1, \
|
||||
MAX(c12) OVER window2 AS max1 \
|
||||
|
|
@ -5875,8 +5874,8 @@ fn test_parse_named_window() {
|
|||
#[test]
|
||||
fn parse_window_and_qualify_clause() {
|
||||
let dialects = all_dialects_except(|d| {
|
||||
d.is_table_alias(&Keyword::WINDOW, &mut Parser::new(d))
|
||||
|| d.is_table_alias(&Keyword::QUALIFY, &mut Parser::new(d))
|
||||
d.is_table_alias(&Keyword::WINDOW, &Parser::new(d))
|
||||
|| d.is_table_alias(&Keyword::QUALIFY, &Parser::new(d))
|
||||
});
|
||||
let sql = "SELECT \
|
||||
MIN(c12) OVER window1 AS min1 \
|
||||
|
|
@ -7614,7 +7613,7 @@ fn parse_join_syntax_variants() {
|
|||
"SELECT c1 FROM t1 FULL JOIN t2 USING(c1)",
|
||||
);
|
||||
|
||||
let dialects = all_dialects_except(|d| d.is_table_alias(&Keyword::OUTER, &mut Parser::new(d)));
|
||||
let dialects = all_dialects_except(|d| d.is_table_alias(&Keyword::OUTER, &Parser::new(d)));
|
||||
let res = dialects.parse_sql_statements("SELECT * FROM a OUTER JOIN b ON 1");
|
||||
assert_eq!(
|
||||
ParserError::ParserError("Expected: APPLY, found: JOIN".to_string()),
|
||||
|
|
@ -7829,7 +7828,7 @@ fn parse_union_except_intersect_minus() {
|
|||
|
||||
// Dialects that support `MINUS` as column identifier
|
||||
// do not support `MINUS` as a set operator.
|
||||
let dialects = all_dialects_where(|d| !d.is_column_alias(&Keyword::MINUS, &mut Parser::new(d)));
|
||||
let dialects = all_dialects_where(|d| !d.is_column_alias(&Keyword::MINUS, &Parser::new(d)));
|
||||
dialects.verified_stmt("SELECT 1 MINUS SELECT 2");
|
||||
dialects.verified_stmt("SELECT 1 MINUS ALL SELECT 2");
|
||||
dialects.verified_stmt("SELECT 1 MINUS DISTINCT SELECT 1");
|
||||
|
|
@ -8592,8 +8591,7 @@ fn parse_invalid_subquery_without_parens() {
|
|||
fn parse_offset() {
|
||||
// Dialects that support `OFFSET` as column identifiers
|
||||
// don't support this syntax.
|
||||
let dialects =
|
||||
all_dialects_where(|d| !d.is_column_alias(&Keyword::OFFSET, &mut Parser::new(d)));
|
||||
let dialects = all_dialects_where(|d| !d.is_column_alias(&Keyword::OFFSET, &Parser::new(d)));
|
||||
|
||||
let expected_limit_clause = &Some(LimitClause::LimitOffset {
|
||||
limit: None,
|
||||
|
|
@ -12454,7 +12452,7 @@ fn test_buffer_reuse() {
|
|||
Tokenizer::new(&d, q)
|
||||
.tokenize_with_location_into_buf(&mut buf)
|
||||
.unwrap();
|
||||
let mut p = Parser::new(&d).with_tokens_with_locations(buf);
|
||||
let p = Parser::new(&d).with_tokens_with_locations(buf);
|
||||
p.parse_statements().unwrap();
|
||||
let _ = p.into_tokens();
|
||||
}
|
||||
|
|
@ -15368,7 +15366,7 @@ fn parse_case_statement() {
|
|||
#[test]
|
||||
fn test_case_statement_span() {
|
||||
let sql = "CASE 1 WHEN 2 THEN SELECT 1; SELECT 2; ELSE SELECT 3; END CASE";
|
||||
let mut parser = Parser::new(&GenericDialect {}).try_with_sql(sql).unwrap();
|
||||
let parser = Parser::new(&GenericDialect {}).try_with_sql(sql).unwrap();
|
||||
assert_eq!(
|
||||
parser.parse_statement().unwrap().span(),
|
||||
Span::new(Location::new(1, 1), Location::new(1, sql.len() as u64 + 1))
|
||||
|
|
@ -15449,7 +15447,7 @@ fn parse_if_statement() {
|
|||
#[test]
|
||||
fn test_if_statement_span() {
|
||||
let sql = "IF 1=1 THEN SELECT 1; ELSEIF 1=2 THEN SELECT 2; ELSE SELECT 3; END IF";
|
||||
let mut parser = Parser::new(&GenericDialect {}).try_with_sql(sql).unwrap();
|
||||
let parser = Parser::new(&GenericDialect {}).try_with_sql(sql).unwrap();
|
||||
assert_eq!(
|
||||
parser.parse_statement().unwrap().span(),
|
||||
Span::new(Location::new(1, 1), Location::new(1, sql.len() as u64 + 1))
|
||||
|
|
@ -15463,7 +15461,7 @@ fn test_if_statement_multiline_span() {
|
|||
let sql_line3 = "ELSE SELECT 3;";
|
||||
let sql_line4 = "END IF";
|
||||
let sql = [sql_line1, sql_line2, sql_line3, sql_line4].join("\n");
|
||||
let mut parser = Parser::new(&GenericDialect {}).try_with_sql(&sql).unwrap();
|
||||
let parser = Parser::new(&GenericDialect {}).try_with_sql(&sql).unwrap();
|
||||
assert_eq!(
|
||||
parser.parse_statement().unwrap().span(),
|
||||
Span::new(
|
||||
|
|
@ -15476,7 +15474,7 @@ fn test_if_statement_multiline_span() {
|
|||
#[test]
|
||||
fn test_conditional_statement_span() {
|
||||
let sql = "IF 1=1 THEN SELECT 1; ELSEIF 1=2 THEN SELECT 2; ELSE SELECT 3; END IF";
|
||||
let mut parser = Parser::new(&GenericDialect {}).try_with_sql(sql).unwrap();
|
||||
let parser = Parser::new(&GenericDialect {}).try_with_sql(sql).unwrap();
|
||||
match parser.parse_statement().unwrap() {
|
||||
Statement::If(IfStatement {
|
||||
if_block,
|
||||
|
|
@ -16958,7 +16956,7 @@ fn test_select_exclude() {
|
|||
let dialects = all_dialects_where(|d| {
|
||||
d.supports_select_wildcard_exclude()
|
||||
&& !d.supports_select_exclude()
|
||||
&& d.is_column_alias(&Keyword::EXCLUDE, &mut Parser::new(d))
|
||||
&& d.is_column_alias(&Keyword::EXCLUDE, &Parser::new(d))
|
||||
});
|
||||
assert_eq!(
|
||||
dialects
|
||||
|
|
@ -16973,7 +16971,7 @@ fn test_select_exclude() {
|
|||
let dialects = all_dialects_where(|d| {
|
||||
d.supports_select_wildcard_exclude()
|
||||
&& !d.supports_select_exclude()
|
||||
&& !d.is_column_alias(&Keyword::EXCLUDE, &mut Parser::new(d))
|
||||
&& !d.is_column_alias(&Keyword::EXCLUDE, &Parser::new(d))
|
||||
});
|
||||
assert_eq!(
|
||||
dialects
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ fn custom_prefix_parser() -> Result<(), ParserError> {
|
|||
is_identifier_part(ch)
|
||||
}
|
||||
|
||||
fn parse_prefix(&self, parser: &mut Parser) -> Option<Result<Expr, ParserError>> {
|
||||
fn parse_prefix(&self, parser: &Parser) -> Option<Result<Expr, ParserError>> {
|
||||
if parser.consume_token(&Token::Number("1".to_string(), false)) {
|
||||
Some(Ok(Expr::Value(Value::Null.with_empty_span())))
|
||||
} else {
|
||||
|
|
@ -72,7 +72,7 @@ fn custom_infix_parser() -> Result<(), ParserError> {
|
|||
|
||||
fn parse_infix(
|
||||
&self,
|
||||
parser: &mut Parser,
|
||||
parser: &Parser,
|
||||
expr: &Expr,
|
||||
_precedence: u8,
|
||||
) -> Option<Result<Expr, ParserError>> {
|
||||
|
|
@ -110,7 +110,7 @@ fn custom_statement_parser() -> Result<(), ParserError> {
|
|||
is_identifier_part(ch)
|
||||
}
|
||||
|
||||
fn parse_statement(&self, parser: &mut Parser) -> Option<Result<Statement, ParserError>> {
|
||||
fn parse_statement(&self, parser: &Parser) -> Option<Result<Statement, ParserError>> {
|
||||
if parser.parse_keyword(Keyword::SELECT) {
|
||||
for _ in 0..3 {
|
||||
let _ = parser.next_token();
|
||||
|
|
|
|||
|
|
@ -2213,7 +2213,7 @@ fn parse_mssql_if_else() {
|
|||
#[test]
|
||||
fn test_mssql_if_else_span() {
|
||||
let sql = "IF 1 = 1 SELECT '1' ELSE SELECT '2'";
|
||||
let mut parser = Parser::new(&MsSqlDialect {}).try_with_sql(sql).unwrap();
|
||||
let parser = Parser::new(&MsSqlDialect {}).try_with_sql(sql).unwrap();
|
||||
assert_eq!(
|
||||
parser.parse_statement().unwrap().span(),
|
||||
Span::new(Location::new(1, 1), Location::new(1, sql.len() as u64 + 1))
|
||||
|
|
@ -2226,7 +2226,7 @@ fn test_mssql_if_else_multiline_span() {
|
|||
let sql_line2 = "SELECT '1'";
|
||||
let sql_line3 = "ELSE SELECT '2'";
|
||||
let sql = [sql_line1, sql_line2, sql_line3].join("\n");
|
||||
let mut parser = Parser::new(&MsSqlDialect {}).try_with_sql(&sql).unwrap();
|
||||
let parser = Parser::new(&MsSqlDialect {}).try_with_sql(&sql).unwrap();
|
||||
assert_eq!(
|
||||
parser.parse_statement().unwrap().span(),
|
||||
Span::new(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue