Skip to main content

robin_sparkless/sql/
parser.rs

1//! Parse SQL into sqlparser AST.
2
3use polars::prelude::PolarsError;
4use sqlparser::ast::Statement;
5use sqlparser::dialect::GenericDialect;
6use sqlparser::parser::Parser;
7
8/// Parse a single SQL statement (SELECT or DDL: CREATE SCHEMA / CREATE DATABASE / DROP TABLE).
9pub fn parse_sql(query: &str) -> Result<Statement, PolarsError> {
10    let dialect = GenericDialect {};
11    let stmts = Parser::parse_sql(&dialect, query).map_err(|e| {
12        PolarsError::InvalidOperation(
13            format!(
14                "SQL parse error: {}. Hint: only SELECT and CREATE SCHEMA/DATABASE/DROP TABLE/VIEW/SCHEMA are supported.",
15                e
16            )
17            .into(),
18        )
19    })?;
20    if stmts.len() != 1 {
21        return Err(PolarsError::InvalidOperation(
22            format!(
23                "SQL: expected exactly one statement, got {}. Hint: run one statement at a time.",
24                stmts.len()
25            )
26            .into(),
27        ));
28    }
29    let stmt = stmts.into_iter().next().unwrap();
30    match &stmt {
31        Statement::Query(_) => {}
32        Statement::CreateSchema { .. } | Statement::CreateDatabase { .. } => {}
33        Statement::Drop {
34            object_type:
35                sqlparser::ast::ObjectType::Table
36                | sqlparser::ast::ObjectType::View
37                | sqlparser::ast::ObjectType::Schema,
38            ..
39        } => {}
40        _ => {
41            return Err(PolarsError::InvalidOperation(
42                format!(
43                    "SQL: only SELECT, CREATE SCHEMA/DATABASE, and DROP TABLE/VIEW/SCHEMA are supported, got {:?}.",
44                    stmt
45                )
46                .into(),
47            ));
48        }
49    }
50    Ok(stmt)
51}