1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
use crate::{
ast::Statement,
lexer::{Modifier, TokenKind},
parser::{expression::modifiers::CreateModifiers, parser::Parser, parser_error::ParserError},
};
impl<'a> Parser<'a> {
/// Parses the entire token stream into a list of SQL statements.
///
/// Statements are separated by semicolons. Empty statements
/// (consecutive semicolons) are ignored.
///
/// # Returns
///
/// A vector containing all successfully parsed statements,
/// or a [`ParserError`] if parsing fails.
pub fn parse(&mut self) -> Result<Vec<Statement>, ParserError> {
let mut stmts = vec![];
while !self.is_at_end() {
if self.consume(&TokenKind::Semicolon) {
continue;
}
stmts.push(self.parse_statement()?);
}
Ok(stmts)
}
/// Parses a single SQL statement.
///
/// Dispatches parsing based on the current token and supports
/// SELECT, WITH, CREATE, DROP, ALTER, and TRUNCATE statements.
///
/// Trailing semicolons are consumed automatically.
///
/// # Errors
///
/// Returns a [`ParserError`] if the current token does not begin
/// a valid statement.
fn parse_statement(&mut self) -> Result<Statement, ParserError> {
let stmt = match self.current_token() {
TokenKind::Select | TokenKind::With => Statement::Select(self.parse_select()?),
TokenKind::Truncate => Statement::TruncateTable(self.parse_truncate()?),
TokenKind::Create => self.parse_create()?,
TokenKind::Drop => self.parse_drop()?,
TokenKind::Alter => self.parse_alter()?,
TokenKind::Insert => Statement::Insert(self.parser_insert()?),
TokenKind::Use => {
self.advance();
Statement::UseDatabase(self.parse_use_database()?)
}
_ => {
return Err(ParserError::new(
format!("Unexpected token {:?}", self.current_token()),
self.current.span.clone(),
));
}
};
self.consume(&TokenKind::Semicolon);
Ok(stmt)
}
/// Parses optional modifiers that can appear after a `CREATE`
/// keyword.
///
/// Supported modifiers include:
///
/// - `OR REPLACE`
/// - `TEMPORARY` / `TEMP`
/// - `UNLOGGED`
/// - `MATERIALIZED`
/// - `UNIQUE`
/// - `LOCAL`
/// - `GLOBAL`
///
/// Returns a [`CreateModifiers`] structure describing all
/// detected modifiers.
pub fn parse_create_modifiers(&mut self) -> CreateModifiers {
let mut m = CreateModifiers {
or_replace: false,
temporary: false,
unlogged: false,
unique: false,
materialized: false,
};
loop {
match self.current_token() {
TokenKind::Or => {
self.advance();
if let TokenKind::Modifier(Modifier::Replace) = self.current_token() {
self.advance();
m.or_replace = true;
}
}
TokenKind::Modifier(Modifier::Replace) => {
self.advance();
m.or_replace = true;
}
TokenKind::Modifier(Modifier::Temporary) | TokenKind::Modifier(Modifier::Temp) => {
self.advance();
m.temporary = true;
}
TokenKind::Modifier(Modifier::Unlogged) => {
self.advance();
m.unlogged = true;
}
TokenKind::Modifier(Modifier::Materialized) => {
self.advance();
m.materialized = true;
}
TokenKind::Modifier(Modifier::Local) | TokenKind::Modifier(Modifier::Global) => {
self.advance();
}
TokenKind::Unique => {
self.advance();
m.unique = true;
}
_ => break,
}
}
m
}
}