Skip to main content

citadel_sql/
dialect.rs

1use sqlparser::ast::Expr as SpExpr;
2use sqlparser::ast::Statement as SpStatement;
3use sqlparser::dialect::{Dialect, GenericDialect, PostgreSqlDialect};
4use sqlparser::parser::{Parser, ParserError};
5
6/// PG dialect first (for `?` / `?|` / `?&` JSON ops + TRUNCATE CASCADE);
7/// fall back to Generic on parse error (for SQLite-style `TRIM(s, c)` etc.).
8pub fn parse_statements(sql: &str) -> Result<Vec<SpStatement>, ParserError> {
9    parse_with_fallback(sql, Parser::parse_sql)
10}
11
12pub fn parse_expr(sql: &str) -> Result<SpExpr, ParserError> {
13    parse_with_fallback(sql, |dialect, sql| {
14        Parser::new(dialect).try_with_sql(sql)?.parse_expr()
15    })
16}
17
18fn parse_with_fallback<T, F>(sql: &str, parse_fn: F) -> Result<T, ParserError>
19where
20    F: Fn(&dyn Dialect, &str) -> Result<T, ParserError>,
21{
22    let pg = PostgreSqlDialect {};
23    match parse_fn(&pg, sql) {
24        Ok(r) => Ok(r),
25        Err(pg_err) => {
26            let generic = GenericDialect {};
27            parse_fn(&generic, sql).map_err(|_| pg_err)
28        }
29    }
30}
31
32#[cfg(test)]
33#[path = "dialect_tests.rs"]
34mod tests;