Skip to content

Commit a27ca8b

Browse files
committed
sql_parser: sqlite3 statement parser refactoring
1 parent 4fa1386 commit a27ca8b

File tree

6 files changed

+259
-509
lines changed

6 files changed

+259
-509
lines changed

README.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -16,22 +16,22 @@ The items were taken from the official SQLite documentation
1616
[here](https://www.sqlite.org/lang.html)
1717

1818
### Simple statements ![progress](https://progress-bar.xyz/14/?scale=14&suffix=%%%20(14%20of%2014)&width=140)
19-
1. [drop-stmt](https://www.sqlite.org/lang_droptable.html) ✅
19+
1. [drop-stmt](https://www.sqlite.org/lang_droptable.html)
2020
1. [drop-table-stmt](https://www.sqlite.org/lang_droptable.html) ✅
2121
1. [drop-index-stmt](https://www.sqlite.org/lang_dropindex.html) ✅
2222
1. [drop-trigger-stmt](https://www.sqlite.org/lang_droptrigger.html) ✅
2323
1. [drop-view-stmt](https://www.sqlite.org/lang_dropview.html) ✅
24-
1. [sqlite3-stmt](https://www.sqlite.org/lang_vacuum.html) ✅
24+
1. [sqlite3-stmt](https://www.sqlite.org/lang_vacuum.html)
2525
1. [vacuum-stmt](https://www.sqlite.org/lang_vacuum.html) ✅
2626
1. [detach-stmt](https://www.sqlite.org/lang_detach.html) ✅
2727
1. [analyze-stmt](https://www.sqlite.org/lang_analyze.html) ✅
2828
1. [reindex-stmt](https://www.sqlite.org/lang_reindex.html) ✅
29-
1. [pragma-stmt](https://www.sqlite.org/pragma.html) ✅
29+
1. [pragma-stmt](https://www.sqlite.org/pragma.html)
3030
1. [transaction-stmt](https://www.sqlite.org/lang_transaction.html) ✅
3131
1. [begin-stmt](https://www.sqlite.org/lang_transaction.html) ✅
3232
1. [commit-stmt](https://www.sqlite.org/lang_transaction.html) ✅
3333
1. [rollback-stmt](https://www.sqlite.org/lang_savepoint.html) ✅
34-
1. [savepoint-stmt](https://www.sqlite.org/lang_savepoint.html) ✅
34+
1. [savepoint-stmt](https://www.sqlite.org/lang_savepoint.html)
3535
1. [savepoint-stmt](https://www.sqlite.org/lang_savepoint.html) ✅
3636
1. [release-stmt](https://www.sqlite.org/lang_savepoint.html) ✅
3737

src/parser/sqlite/analyze.rs

+57-91
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,11 @@ impl<'a> AnalyzeStatementParser for Parser<'a> {
2727
}));
2828
}
2929

30-
let mut table_or_index_name: Option<String> = None;
31-
if self.peek_as(TokenType::Dot).is_ok() {
32-
self.consume_as(TokenType::Dot)?;
33-
34-
table_or_index_name = Some(self.parse_sqlite3_name()?);
35-
}
30+
let table_or_index_name: Option<String> = if self.consume_as(TokenType::Dot).is_ok() {
31+
Some(self.parse_sqlite3_name()?)
32+
} else {
33+
None
34+
};
3635

3736
self.finalize_statement_parsing()?;
3837

@@ -59,124 +58,104 @@ pub mod test_utils {
5958
mod analyze_statements_tests {
6059
use crate::ast::AnalyzeStatement;
6160
use crate::parser::errors::ParsingError;
62-
use crate::parser::test_utils::{run_rainy_day_test, run_sunny_day_test};
61+
use crate::parser::test_utils::{
62+
assert_statements_equal, run_rainy_day_test, run_sunny_day_test,
63+
};
6364
use crate::{Parser, Statement};
6465

6566
use super::test_utils::analyze_statement;
6667

6768
#[test]
6869
fn test_analyze_basic() {
69-
let sql = "ANALYZE;";
70-
run_sunny_day_test(sql, Statement::Analyze(analyze_statement()));
70+
run_sunny_day_test("ANALYZE;", Statement::Analyze(analyze_statement()));
7171
}
7272

7373
#[test]
7474
fn test_analyze_with_schema_name() {
75-
let sql = "ANALYZE main;";
76-
run_sunny_day_test(
77-
sql,
78-
Statement::Analyze(AnalyzeStatement {
79-
schema_name: Some("main".to_string()),
80-
table_or_index_name: None,
81-
}),
82-
);
75+
let mut expected_statement = analyze_statement();
76+
expected_statement.schema_name = Some("main".to_string());
77+
78+
run_sunny_day_test("ANALYZE main;", Statement::Analyze(expected_statement));
8379
}
8480

8581
#[test]
8682
fn test_analyze_with_schema_and_table() {
87-
let sql = "ANALYZE main.my_table;";
83+
let mut expected_statement = analyze_statement();
84+
expected_statement.schema_name = Some("main".to_string());
85+
expected_statement.table_or_index_name = Some("my_table".to_string());
86+
8887
run_sunny_day_test(
89-
sql,
90-
Statement::Analyze(AnalyzeStatement {
91-
schema_name: Some("main".to_string()),
92-
table_or_index_name: Some("my_table".to_string()),
93-
}),
88+
"ANALYZE main.my_table;",
89+
Statement::Analyze(expected_statement),
9490
);
9591
}
9692

9793
#[test]
9894
fn test_analyze_with_single_quoted_schema() {
99-
let sql = "ANALYZE 'main';";
100-
run_sunny_day_test(
101-
sql,
102-
Statement::Analyze(AnalyzeStatement {
103-
schema_name: Some("'main'".to_string()),
104-
table_or_index_name: None,
105-
}),
106-
);
95+
let mut expected_statement = analyze_statement();
96+
expected_statement.schema_name = Some("'main'".to_string());
97+
98+
run_sunny_day_test("ANALYZE 'main';", Statement::Analyze(expected_statement));
10799
}
108100

109101
#[test]
110102
fn test_analyze_with_double_quoted_schema() {
111-
let sql = "ANALYZE \"main\";";
112-
run_sunny_day_test(
113-
sql,
114-
Statement::Analyze(AnalyzeStatement {
115-
schema_name: Some("\"main\"".to_string()),
116-
table_or_index_name: None,
117-
}),
118-
);
103+
let mut expected_statement = analyze_statement();
104+
expected_statement.schema_name = Some("\"main\"".to_string());
105+
106+
run_sunny_day_test("ANALYZE \"main\";", Statement::Analyze(expected_statement));
119107
}
120108

121109
#[test]
122110
fn test_analyze_with_single_quoted_schema_and_table() {
123-
let sql = "ANALYZE 'main'.'my_table';";
111+
let mut expected_statement = analyze_statement();
112+
expected_statement.schema_name = Some("'main'".to_string());
113+
expected_statement.table_or_index_name = Some("'my_table'".to_string());
114+
124115
run_sunny_day_test(
125-
sql,
126-
Statement::Analyze(AnalyzeStatement {
127-
schema_name: Some("'main'".to_string()),
128-
table_or_index_name: Some("'my_table'".to_string()),
129-
}),
116+
"ANALYZE 'main'.'my_table';",
117+
Statement::Analyze(expected_statement),
130118
);
131119
}
132120

133121
#[test]
134122
fn test_analyze_with_double_quoted_schema_and_table() {
135-
let sql = "ANALYZE \"main\".\"my_table\";";
123+
let mut expected_statement = analyze_statement();
124+
expected_statement.schema_name = Some("\"main\"".to_string());
125+
expected_statement.table_or_index_name = Some("\"my_table\"".to_string());
126+
136127
run_sunny_day_test(
137-
sql,
138-
Statement::Analyze(AnalyzeStatement {
139-
schema_name: Some("\"main\"".to_string()),
140-
table_or_index_name: Some("\"my_table\"".to_string()),
141-
}),
128+
"ANALYZE \"main\".\"my_table\";",
129+
Statement::Analyze(expected_statement),
142130
);
143131
}
144132

145133
#[test]
146134
fn test_analyze_missing_semicolon() {
147135
let sql = "ANALYZE";
148-
run_sunny_day_test(
149-
sql,
150-
Statement::Analyze(AnalyzeStatement {
151-
schema_name: None,
152-
table_or_index_name: None,
153-
}),
154-
);
136+
run_sunny_day_test(sql, Statement::Analyze(analyze_statement()));
155137
}
156138

157139
#[test]
158140
fn test_analyze_with_invalid_schema_name() {
159-
let sql = "ANALYZE 'unclosed_schema;";
160141
run_rainy_day_test(
161-
sql,
142+
"ANALYZE 'unclosed_schema;",
162143
ParsingError::TokenizerError("UnterminatedLiteral: 'unclosed_schema;".into()),
163144
);
164145
}
165146

166147
#[test]
167148
fn test_analyze_with_invalid_table_name() {
168-
let sql = "ANALYZE main.'unclosed_table;";
169149
run_rainy_day_test(
170-
sql,
150+
"ANALYZE main.'unclosed_table;",
171151
ParsingError::TokenizerError("UnterminatedLiteral: 'unclosed_table;".into()),
172152
);
173153
}
174154

175155
#[test]
176156
fn test_analyze_with_numeric_schema_name() {
177-
let sql = "ANALYZE '123';";
178157
run_sunny_day_test(
179-
sql,
158+
"ANALYZE '123';",
180159
Statement::Analyze(AnalyzeStatement {
181160
schema_name: Some("'123'".to_string()),
182161
table_or_index_name: None,
@@ -186,9 +165,8 @@ mod analyze_statements_tests {
186165

187166
#[test]
188167
fn test_analyze_with_numeric_table_name() {
189-
let sql = "ANALYZE main.'123';";
190168
run_sunny_day_test(
191-
sql,
169+
"ANALYZE main.'123';",
192170
Statement::Analyze(AnalyzeStatement {
193171
schema_name: Some("main".to_string()),
194172
table_or_index_name: Some("'123'".to_string()),
@@ -198,9 +176,8 @@ mod analyze_statements_tests {
198176

199177
#[test]
200178
fn test_analyze_with_escaped_quotes_in_schema_name() {
201-
let sql = "ANALYZE 'main''db';";
202179
run_sunny_day_test(
203-
sql,
180+
"ANALYZE 'main''db';",
204181
Statement::Analyze(AnalyzeStatement {
205182
schema_name: Some("'main''db'".to_string()),
206183
table_or_index_name: None,
@@ -210,9 +187,8 @@ mod analyze_statements_tests {
210187

211188
#[test]
212189
fn test_analyze_with_escaped_quotes_in_table_name() {
213-
let sql = "ANALYZE main.'table''name';";
214190
run_sunny_day_test(
215-
sql,
191+
"ANALYZE main.'table''name';",
216192
Statement::Analyze(AnalyzeStatement {
217193
schema_name: Some("main".to_string()),
218194
table_or_index_name: Some("'table''name'".to_string()),
@@ -222,9 +198,8 @@ mod analyze_statements_tests {
222198

223199
#[test]
224200
fn test_analyze_with_backticks_schema_name() {
225-
let sql = "ANALYZE `main`;";
226201
run_sunny_day_test(
227-
sql,
202+
"ANALYZE `main`;",
228203
Statement::Analyze(AnalyzeStatement {
229204
schema_name: Some("`main`".to_string()),
230205
table_or_index_name: None,
@@ -234,9 +209,8 @@ mod analyze_statements_tests {
234209

235210
#[test]
236211
fn test_analyze_with_special_chars_in_table_name() {
237-
let sql = "ANALYZE main.'[email protected]!';";
238212
run_sunny_day_test(
239-
sql,
213+
"ANALYZE main.'[email protected]!';",
240214
Statement::Analyze(AnalyzeStatement {
241215
schema_name: Some("main".to_string()),
242216
table_or_index_name: Some("'[email protected]!'".to_string()),
@@ -249,30 +223,22 @@ mod analyze_statements_tests {
249223
let sql = "ANALYZE; ANALYZE main.my_table;";
250224
let mut parser = Parser::from(sql);
251225

226+
let first_expected_statement = Statement::Analyze(analyze_statement());
227+
252228
let first_actual_statement = parser
253229
.parse_statement()
254230
.expect("Expected parsed Statement, got Parsing Error");
255-
let first_expected_statement = Statement::Analyze(AnalyzeStatement {
256-
schema_name: None,
257-
table_or_index_name: None,
258-
});
259-
assert_eq!(
260-
first_actual_statement, first_expected_statement,
261-
"Expected statement {:?}, got {:?}",
262-
first_expected_statement, first_actual_statement
263-
);
264231

265-
let second_actual_statement = parser
266-
.parse_statement()
267-
.expect("Expected parsed Statement, got Parsing Error");
232+
assert_statements_equal(first_expected_statement, first_actual_statement);
268233
let second_expected_statement = Statement::Analyze(AnalyzeStatement {
269234
schema_name: Some("main".to_string()),
270235
table_or_index_name: Some("my_table".to_string()),
271236
});
272-
assert_eq!(
273-
second_actual_statement, second_expected_statement,
274-
"Expected statement {:?}, got {:?}",
275-
second_expected_statement, second_actual_statement
276-
);
237+
238+
let second_actual_statement = parser
239+
.parse_statement()
240+
.expect("Expected parsed Statement, got Parsing Error");
241+
242+
assert_statements_equal(second_expected_statement, second_actual_statement);
277243
}
278244
}

0 commit comments

Comments
 (0)