mod engine;
mod lexer;
mod keywords;
mod tokens;
mod formatter;
mod filters;
mod trie;
pub use tokens::TokenType;
pub use lexer::{Token, TokenList};
pub use formatter::{FormatOption};
pub use engine::grouping::group_tokenlist;
pub use trie::Trie;
pub struct Parser {
stack: engine::FilterStack,
}
impl Default for Parser {
fn default() -> Self {
Self { stack: engine::FilterStack::new() }
}
}
impl Parser {
pub fn new() -> Self {
Self { stack: engine::FilterStack::new() }
}
pub fn parse(&self, sql: &str) -> Vec<Token> {
self.stack.run(sql, true)
}
pub fn parse_multi(&self, sql: &str) -> Vec<Vec<Token>> {
self.stack.run_multi(sql, true)
}
pub fn parse_no_grouping(&self, sql: &str) -> Vec<Token> {
self.stack.run(sql, false)
}
pub fn parse_multi_no_grouping(&self, sql: &str) -> Vec<Vec<Token>> {
self.stack.run_multi(sql, false)
}
}
pub fn parse(sql: &str) -> Vec<Token> {
let stack = engine::FilterStack::new();
stack.run(sql, true)
}
pub fn parse_multi(sql: &str) -> Vec<Vec<Token>> {
let stack = engine::FilterStack::new();
stack.run_multi(sql, true)
}
pub fn parse_no_grouping(sql: &str) -> Vec<Token> {
let stack = engine::FilterStack::new();
stack.run(sql, false)
}
pub struct Formatter {
stack: engine::FilterStack,
}
impl Default for Formatter {
fn default() -> Self {
Self { stack: engine::FilterStack::new() }
}
}
impl Formatter {
pub fn new(stack: engine::FilterStack) -> Self {
Self { stack }
}
pub fn format(&mut self, mut sql: &str, options: &mut formatter::FormatOption) -> String {
formatter::validate_options(options);
formatter::build_filter_stack(&mut self.stack, options);
if options.strip_whitespace { sql = sql.trim(); };
let tokens = self.stack.format(sql, options.grouping);
tokens.iter().map(|token| token.iter().map(|t| t.value.as_str()).collect::<String>()).collect::<Vec<_>>().join("\n")
}
pub fn build_filters(&mut self, options: &mut formatter::FormatOption) {
formatter::validate_options(options);
formatter::build_filter_stack(&mut self.stack, options);
}
pub fn format_sql(&mut self, sql: &str, options: &formatter::FormatOption) -> String {
let tokens = self.stack.format(sql, options.grouping);
tokens.iter().map(|token| token.iter().map(|t| t.value.as_str()).collect::<String>()).collect::<Vec<_>>().join("\n")
}
}
pub fn format(mut sql: &str, options: &mut formatter::FormatOption) -> String {
let mut stack = engine::FilterStack::new();
formatter::validate_options(options);
formatter::build_filter_stack(&mut stack, options);
if options.strip_whitespace { sql = sql.trim(); };
let tokens = stack.format(sql, options.grouping);
tokens.iter().map(|token| token.iter().map(|t| t.value.as_str()).collect::<String>()).collect::<Vec<_>>().join("\n")
}
#[cfg(test)]
mod tests {
use super::*;
use std::time::Instant;
#[test]
fn test_parse() {
let sql = "select * from users where id > 1 order by id;";
let tokens = parse(sql);
for token in tokens {
println!("{:?}", token);
}
}
#[test]
fn test_parse_identifier() {
let sql = "select * from sch.users;";
let tokens = parse(sql);
for token in tokens {
println!("{:?} {}", token.typ, token.value);
}
}
#[test]
fn test_parser1() {
let sql= "SELECT article, MAX(price) AS price FROM shop GROUP BY article ORDER BY article;";
let p = Parser::default();
let now = Instant::now();
let _tokens = p.parse(sql);
let elapsed = now.elapsed();
println!("elapsed: {}ms", elapsed.as_millis());
}
#[test]
fn test_parser2() {
let sql= "s";
let p = Parser::default();
let tokens = p.parse(sql);
assert_eq!(tokens.len(), 1);
assert_eq!(tokens[0].typ, TokenType::Identifier);
println!("{:?}", tokens);
}
#[test]
fn test_parser3() {
let sql= "SELECT COUNT(CustomerID), Country FROM Customers GROUP BY Country HAVING COUNT(CustomerID) > 5 ORDER BY COUNT(CustomerID) DESC;";
let p = Parser::default();
let now = Instant::now();
let _tokens = p.parse(sql);
let elapsed = now.elapsed();
println!("elapsed: {}ms", elapsed.as_millis());
}
}