1
2mod engine;
38mod lexer;
39mod keywords;
40mod tokens;
41mod formatter;
42mod filters;
43mod trie;
44
45
46pub use tokens::TokenType;
47pub use lexer::{Token, TokenList};
48pub use formatter::{FormatOption};
49pub use engine::grouping::group_tokenlist;
50pub use trie::Trie;
51
52pub struct Parser {
54 stack: engine::FilterStack,
55}
56
57impl Default for Parser {
58 fn default() -> Self {
59 Self { stack: engine::FilterStack::new() }
60 }
61}
62
63impl Parser {
65
66 pub fn new() -> Self {
67 Self { stack: engine::FilterStack::new() }
68 }
69
70 pub fn parse(&self, sql: &str) -> Vec<Token> {
72 self.stack.run(sql, true)
73 }
74
75 pub fn parse_multi(&self, sql: &str) -> Vec<Vec<Token>> {
77 self.stack.run_multi(sql, true)
78 }
79
80 pub fn parse_no_grouping(&self, sql: &str) -> Vec<Token> {
81 self.stack.run(sql, false)
82 }
83
84 pub fn parse_multi_no_grouping(&self, sql: &str) -> Vec<Vec<Token>> {
85 self.stack.run_multi(sql, false)
86 }
87}
88
89pub fn parse(sql: &str) -> Vec<Token> {
92 let stack = engine::FilterStack::new();
93 stack.run(sql, true)
94}
95
96pub fn parse_multi(sql: &str) -> Vec<Vec<Token>> {
99 let stack = engine::FilterStack::new();
100 stack.run_multi(sql, true)
101}
102
103pub fn parse_no_grouping(sql: &str) -> Vec<Token> {
106 let stack = engine::FilterStack::new();
107 stack.run(sql, false)
108}
109
110pub struct Formatter {
112 stack: engine::FilterStack,
113}
114
115
116impl Default for Formatter {
117 fn default() -> Self {
118 Self { stack: engine::FilterStack::new() }
119 }
120}
121
122impl Formatter {
123
124 pub fn new(stack: engine::FilterStack) -> Self {
125 Self { stack }
126 }
127
128 pub fn format(&mut self, mut sql: &str, options: &mut formatter::FormatOption) -> String {
130 formatter::validate_options(options);
131 formatter::build_filter_stack(&mut self.stack, options);
132 if options.strip_whitespace { sql = sql.trim(); };
133 let tokens = self.stack.format(sql, options.grouping);
134 tokens.iter().map(|token| token.iter().map(|t| t.value.as_str()).collect::<String>()).collect::<Vec<_>>().join("\n")
135 }
136
137 pub fn build_filters(&mut self, options: &mut formatter::FormatOption) {
138 formatter::validate_options(options);
139 formatter::build_filter_stack(&mut self.stack, options);
140 }
141
142 pub fn format_sql(&mut self, sql: &str, options: &formatter::FormatOption) -> String {
143 let tokens = self.stack.format(sql, options.grouping);
144 tokens.iter().map(|token| token.iter().map(|t| t.value.as_str()).collect::<String>()).collect::<Vec<_>>().join("\n")
145 }
146}
147
148pub fn format(mut sql: &str, options: &mut formatter::FormatOption) -> String {
151 let mut stack = engine::FilterStack::new();
152 formatter::validate_options(options);
153 formatter::build_filter_stack(&mut stack, options);
154 if options.strip_whitespace { sql = sql.trim(); };
155 let tokens = stack.format(sql, options.grouping);
156 tokens.iter().map(|token| token.iter().map(|t| t.value.as_str()).collect::<String>()).collect::<Vec<_>>().join("\n")
160}
161
162#[cfg(test)]
163mod tests {
164 use super::*;
165 use std::time::Instant;
166
167 #[test]
168 fn test_parse() {
169 let sql = "select * from users where id > 1 order by id;";
170 let tokens = parse(sql);
171 for token in tokens {
172 println!("{:?}", token);
173 }
174 }
175
176 #[test]
177 fn test_parse_identifier() {
178 let sql = "select * from sch.users;";
179 let tokens = parse(sql);
180 for token in tokens {
182 println!("{:?} {}", token.typ, token.value);
183 }
184 }
185
186 #[test]
187 fn test_parser1() {
188 let sql= "SELECT article, MAX(price) AS price FROM shop GROUP BY article ORDER BY article;";
189 let p = Parser::default();
190 let now = Instant::now();
191 let _tokens = p.parse(sql);
192 let elapsed = now.elapsed();
193 println!("elapsed: {}ms", elapsed.as_millis());
194 }
195
196
197 #[test]
198 fn test_parser2() {
199 let sql= "s";
200 let p = Parser::default();
201 let tokens = p.parse(sql);
202 assert_eq!(tokens.len(), 1);
203 assert_eq!(tokens[0].typ, TokenType::Identifier);
204 println!("{:?}", tokens);
205 }
206
207 #[test]
208 fn test_parser3() {
209 let sql= "SELECT COUNT(CustomerID), Country FROM Customers GROUP BY Country HAVING COUNT(CustomerID) > 5 ORDER BY COUNT(CustomerID) DESC;";
210 let p = Parser::default();
211 let now = Instant::now();
212 let _tokens = p.parse(sql);
213 let elapsed = now.elapsed();
214 println!("elapsed: {}ms", elapsed.as_millis());
215 }
216
217}