Skip to content

Commit 26b4a46

Browse files
committed
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.
1 parent 954176e commit 26b4a46

File tree

12 files changed

+645
-700
lines changed

12 files changed

+645
-700
lines changed

src/ast/spans.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2371,7 +2371,7 @@ pub mod tests {
23712371
#[test]
23722372
fn test_join() {
23732373
let dialect = &GenericDialect;
2374-
let mut test = SpanTest::new(
2374+
let test = SpanTest::new(
23752375
dialect,
23762376
"SELECT id, name FROM users LEFT JOIN companies ON users.company_id = companies.id",
23772377
);
@@ -2396,7 +2396,7 @@ pub mod tests {
23962396
#[test]
23972397
pub fn test_union() {
23982398
let dialect = &GenericDialect;
2399-
let mut test = SpanTest::new(
2399+
let test = SpanTest::new(
24002400
dialect,
24012401
"SELECT a FROM postgres.public.source UNION SELECT a FROM postgres.public.source",
24022402
);
@@ -2413,7 +2413,7 @@ pub mod tests {
24132413
#[test]
24142414
pub fn test_subquery() {
24152415
let dialect = &GenericDialect;
2416-
let mut test = SpanTest::new(
2416+
let test = SpanTest::new(
24172417
dialect,
24182418
"SELECT a FROM (SELECT a FROM postgres.public.source) AS b",
24192419
);
@@ -2438,7 +2438,7 @@ pub mod tests {
24382438
#[test]
24392439
pub fn test_cte() {
24402440
let dialect = &GenericDialect;
2441-
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");
2441+
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");
24422442

24432443
let query = test.0.parse_query().unwrap();
24442444

@@ -2450,7 +2450,7 @@ pub mod tests {
24502450
#[test]
24512451
pub fn test_snowflake_lateral_flatten() {
24522452
let dialect = &SnowflakeDialect;
2453-
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");
2453+
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");
24542454

24552455
let query = test.0.parse_select().unwrap();
24562456

@@ -2462,7 +2462,7 @@ pub mod tests {
24622462
#[test]
24632463
pub fn test_wildcard_from_cte() {
24642464
let dialect = &GenericDialect;
2465-
let mut test = SpanTest::new(
2465+
let test = SpanTest::new(
24662466
dialect,
24672467
"WITH cte AS (SELECT a FROM postgres.public.source) SELECT cte.* FROM cte",
24682468
);
@@ -2488,7 +2488,7 @@ pub mod tests {
24882488
#[test]
24892489
fn test_case_expr_span() {
24902490
let dialect = &GenericDialect;
2491-
let mut test = SpanTest::new(dialect, "CASE 1 WHEN 2 THEN 3 ELSE 4 END");
2491+
let test = SpanTest::new(dialect, "CASE 1 WHEN 2 THEN 3 ELSE 4 END");
24922492
let expr = test.0.parse_expr().unwrap();
24932493
let expr_span = expr.span();
24942494
assert_eq!(

src/dialect/bigquery.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ const RESERVED_FOR_COLUMN_ALIAS: &[Keyword] = &[
4646
pub struct BigQueryDialect;
4747

4848
impl Dialect for BigQueryDialect {
49-
fn parse_statement(&self, parser: &mut Parser) -> Option<Result<Statement, ParserError>> {
49+
fn parse_statement(&self, parser: &Parser) -> Option<Result<Statement, ParserError>> {
5050
if parser.parse_keyword(Keyword::BEGIN) {
5151
if parser.peek_keyword(Keyword::TRANSACTION)
5252
|| parser.peek_token_ref().token == Token::SemiColon
@@ -145,7 +145,7 @@ impl Dialect for BigQueryDialect {
145145
true
146146
}
147147

148-
fn is_column_alias(&self, kw: &Keyword, _parser: &mut Parser) -> bool {
148+
fn is_column_alias(&self, kw: &Keyword, _parser: &Parser) -> bool {
149149
!RESERVED_FOR_COLUMN_ALIAS.contains(kw)
150150
}
151151

src/dialect/mod.rs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -466,7 +466,7 @@ pub trait Dialect: Debug + Any {
466466
}
467467

468468
/// Dialect-specific prefix parser override
469-
fn parse_prefix(&self, _parser: &mut Parser) -> Option<Result<Expr, ParserError>> {
469+
fn parse_prefix(&self, _parser: &Parser) -> Option<Result<Expr, ParserError>> {
470470
// return None to fall back to the default behavior
471471
None
472472
}
@@ -615,7 +615,7 @@ pub trait Dialect: Debug + Any {
615615
/// If `None` is returned, falls back to the default behavior.
616616
fn parse_infix(
617617
&self,
618-
_parser: &mut Parser,
618+
_parser: &Parser,
619619
_expr: &Expr,
620620
_precedence: u8,
621621
) -> Option<Result<Expr, ParserError>> {
@@ -778,7 +778,7 @@ pub trait Dialect: Debug + Any {
778778
/// This method is called to parse the next statement.
779779
///
780780
/// If `None` is returned, falls back to the default behavior.
781-
fn parse_statement(&self, _parser: &mut Parser) -> Option<Result<Statement, ParserError>> {
781+
fn parse_statement(&self, _parser: &Parser) -> Option<Result<Statement, ParserError>> {
782782
// return None to fall back to the default behavior
783783
None
784784
}
@@ -790,7 +790,7 @@ pub trait Dialect: Debug + Any {
790790
/// If `None` is returned, falls back to the default behavior.
791791
fn parse_column_option(
792792
&self,
793-
_parser: &mut Parser,
793+
_parser: &Parser,
794794
) -> Result<Option<Result<Option<ColumnOption>, ParserError>>, ParserError> {
795795
// return None to fall back to the default behavior
796796
Ok(None)
@@ -1021,33 +1021,33 @@ pub trait Dialect: Debug + Any {
10211021

10221022
/// Returns true if the specified keyword should be parsed as a column identifier.
10231023
/// See [keywords::RESERVED_FOR_COLUMN_ALIAS]
1024-
fn is_column_alias(&self, kw: &Keyword, _parser: &mut Parser) -> bool {
1024+
fn is_column_alias(&self, kw: &Keyword, _parser: &Parser) -> bool {
10251025
!keywords::RESERVED_FOR_COLUMN_ALIAS.contains(kw)
10261026
}
10271027

10281028
/// Returns true if the specified keyword should be parsed as a select item alias.
10291029
/// When explicit is true, the keyword is preceded by an `AS` word. Parser is provided
10301030
/// to enable looking ahead if needed.
1031-
fn is_select_item_alias(&self, explicit: bool, kw: &Keyword, parser: &mut Parser) -> bool {
1031+
fn is_select_item_alias(&self, explicit: bool, kw: &Keyword, parser: &Parser) -> bool {
10321032
explicit || self.is_column_alias(kw, parser)
10331033
}
10341034

10351035
/// Returns true if the specified keyword should be parsed as a table factor identifier.
10361036
/// See [keywords::RESERVED_FOR_TABLE_FACTOR]
1037-
fn is_table_factor(&self, kw: &Keyword, _parser: &mut Parser) -> bool {
1037+
fn is_table_factor(&self, kw: &Keyword, _parser: &Parser) -> bool {
10381038
!keywords::RESERVED_FOR_TABLE_FACTOR.contains(kw)
10391039
}
10401040

10411041
/// Returns true if the specified keyword should be parsed as a table factor alias.
10421042
/// See [keywords::RESERVED_FOR_TABLE_ALIAS]
1043-
fn is_table_alias(&self, kw: &Keyword, _parser: &mut Parser) -> bool {
1043+
fn is_table_alias(&self, kw: &Keyword, _parser: &Parser) -> bool {
10441044
!keywords::RESERVED_FOR_TABLE_ALIAS.contains(kw)
10451045
}
10461046

10471047
/// Returns true if the specified keyword should be parsed as a table factor alias.
10481048
/// When explicit is true, the keyword is preceded by an `AS` word. Parser is provided
10491049
/// to enable looking ahead if needed.
1050-
fn is_table_factor_alias(&self, explicit: bool, kw: &Keyword, parser: &mut Parser) -> bool {
1050+
fn is_table_factor_alias(&self, explicit: bool, kw: &Keyword, parser: &Parser) -> bool {
10511051
explicit || self.is_table_alias(kw, parser)
10521052
}
10531053

@@ -1400,14 +1400,14 @@ mod tests {
14001400

14011401
fn parse_prefix(
14021402
&self,
1403-
parser: &mut sqlparser::parser::Parser,
1403+
parser: &sqlparser::parser::Parser,
14041404
) -> Option<Result<Expr, sqlparser::parser::ParserError>> {
14051405
self.0.parse_prefix(parser)
14061406
}
14071407

14081408
fn parse_infix(
14091409
&self,
1410-
parser: &mut sqlparser::parser::Parser,
1410+
parser: &sqlparser::parser::Parser,
14111411
expr: &Expr,
14121412
precedence: u8,
14131413
) -> Option<Result<Expr, sqlparser::parser::ParserError>> {
@@ -1423,7 +1423,7 @@ mod tests {
14231423

14241424
fn parse_statement(
14251425
&self,
1426-
parser: &mut sqlparser::parser::Parser,
1426+
parser: &sqlparser::parser::Parser,
14271427
) -> Option<Result<Statement, sqlparser::parser::ParserError>> {
14281428
self.0.parse_statement(parser)
14291429
}

src/dialect/mssql.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -128,11 +128,11 @@ impl Dialect for MsSqlDialect {
128128
&[GranteesType::Public]
129129
}
130130

131-
fn is_column_alias(&self, kw: &Keyword, _parser: &mut Parser) -> bool {
131+
fn is_column_alias(&self, kw: &Keyword, _parser: &Parser) -> bool {
132132
!keywords::RESERVED_FOR_COLUMN_ALIAS.contains(kw) && !RESERVED_FOR_COLUMN_ALIAS.contains(kw)
133133
}
134134

135-
fn parse_statement(&self, parser: &mut Parser) -> Option<Result<Statement, ParserError>> {
135+
fn parse_statement(&self, parser: &Parser) -> Option<Result<Statement, ParserError>> {
136136
if parser.peek_keyword(Keyword::IF) {
137137
Some(self.parse_if_stmt(parser))
138138
} else if parser.parse_keywords(&[Keyword::CREATE, Keyword::TRIGGER]) {
@@ -157,7 +157,7 @@ impl MsSqlDialect {
157157
/// [ ELSE
158158
/// { sql_statement | statement_block } ]
159159
/// ```
160-
fn parse_if_stmt(&self, parser: &mut Parser) -> Result<Statement, ParserError> {
160+
fn parse_if_stmt(&self, parser: &Parser) -> Result<Statement, ParserError> {
161161
let if_token = parser.expect_keyword(Keyword::IF)?;
162162

163163
let condition = parser.parse_expr()?;
@@ -240,7 +240,7 @@ impl MsSqlDialect {
240240
/// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-trigger-transact-sql
241241
fn parse_create_trigger(
242242
&self,
243-
parser: &mut Parser,
243+
parser: &Parser,
244244
or_alter: bool,
245245
) -> Result<Statement, ParserError> {
246246
let name = parser.parse_object_name(false)?;
@@ -279,7 +279,7 @@ impl MsSqlDialect {
279279
/// Stops parsing when reaching EOF or the given keyword.
280280
fn parse_statement_list(
281281
&self,
282-
parser: &mut Parser,
282+
parser: &Parser,
283283
terminal_keyword: Option<Keyword>,
284284
) -> Result<Vec<Statement>, ParserError> {
285285
let mut stmts = Vec::new();

src/dialect/mysql.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ impl Dialect for MySqlDialect {
8686

8787
fn parse_infix(
8888
&self,
89-
parser: &mut crate::parser::Parser,
89+
parser: &crate::parser::Parser,
9090
expr: &crate::ast::Expr,
9191
_precedence: u8,
9292
) -> Option<Result<crate::ast::Expr, ParserError>> {
@@ -102,7 +102,7 @@ impl Dialect for MySqlDialect {
102102
}
103103
}
104104

105-
fn parse_statement(&self, parser: &mut Parser) -> Option<Result<Statement, ParserError>> {
105+
fn parse_statement(&self, parser: &Parser) -> Option<Result<Statement, ParserError>> {
106106
if parser.parse_keywords(&[Keyword::LOCK, Keyword::TABLES]) {
107107
Some(parse_lock_tables(parser))
108108
} else if parser.parse_keywords(&[Keyword::UNLOCK, Keyword::TABLES]) {
@@ -134,7 +134,7 @@ impl Dialect for MySqlDialect {
134134
true
135135
}
136136

137-
fn is_table_factor_alias(&self, explicit: bool, kw: &Keyword, _parser: &mut Parser) -> bool {
137+
fn is_table_factor_alias(&self, explicit: bool, kw: &Keyword, _parser: &Parser) -> bool {
138138
explicit
139139
|| (!keywords::RESERVED_FOR_TABLE_ALIAS.contains(kw)
140140
&& !RESERVED_FOR_TABLE_ALIAS_MYSQL.contains(kw))
@@ -171,13 +171,13 @@ impl Dialect for MySqlDialect {
171171

172172
/// `LOCK TABLES`
173173
/// <https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html>
174-
fn parse_lock_tables(parser: &mut Parser) -> Result<Statement, ParserError> {
174+
fn parse_lock_tables(parser: &Parser) -> Result<Statement, ParserError> {
175175
let tables = parser.parse_comma_separated(parse_lock_table)?;
176176
Ok(Statement::LockTables { tables })
177177
}
178178

179179
// tbl_name [[AS] alias] lock_type
180-
fn parse_lock_table(parser: &mut Parser) -> Result<LockTable, ParserError> {
180+
fn parse_lock_table(parser: &Parser) -> Result<LockTable, ParserError> {
181181
let table = parser.parse_identifier()?;
182182
let alias =
183183
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> {
191191
}
192192

193193
// READ [LOCAL] | [LOW_PRIORITY] WRITE
194-
fn parse_lock_tables_type(parser: &mut Parser) -> Result<LockTableType, ParserError> {
194+
fn parse_lock_tables_type(parser: &Parser) -> Result<LockTableType, ParserError> {
195195
if parser.parse_keyword(Keyword::READ) {
196196
if parser.parse_keyword(Keyword::LOCAL) {
197197
Ok(LockTableType::Read { local: true })
@@ -211,6 +211,6 @@ fn parse_lock_tables_type(parser: &mut Parser) -> Result<LockTableType, ParserEr
211211

212212
/// UNLOCK TABLES
213213
/// <https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html>
214-
fn parse_unlock_tables(_parser: &mut Parser) -> Result<Statement, ParserError> {
214+
fn parse_unlock_tables(_parser: &Parser) -> Result<Statement, ParserError> {
215215
Ok(Statement::UnlockTables)
216216
}

0 commit comments

Comments
 (0)