mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-12-23 11:12:51 +00:00
Immutable parser (Tokenize borrow strings cont) (#2098)
Some checks failed
Rust / codestyle (push) Has been cancelled
Rust / lint (push) Has been cancelled
Rust / benchmark-lint (push) Has been cancelled
Rust / compile (push) Has been cancelled
Rust / docs (push) Has been cancelled
Rust / compile-no-std (push) Has been cancelled
Rust / test (beta) (push) Has been cancelled
Rust / test (nightly) (push) Has been cancelled
Rust / test (stable) (push) Has been cancelled
Some checks failed
Rust / codestyle (push) Has been cancelled
Rust / lint (push) Has been cancelled
Rust / benchmark-lint (push) Has been cancelled
Rust / compile (push) Has been cancelled
Rust / docs (push) Has been cancelled
Rust / compile-no-std (push) Has been cancelled
Rust / test (beta) (push) Has been cancelled
Rust / test (nightly) (push) Has been cancelled
Rust / test (stable) (push) Has been cancelled
Co-authored-by: Eyal Leshem <eyal@satoricyber.com>
This commit is contained in:
parent
b098976cab
commit
c6933bb8ec
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