1pub mod aggregate_walk;
14pub mod catalog;
15pub mod coerce;
16pub mod ddl_ast;
17pub mod dsl_bind;
18pub mod engine_rules;
19pub mod error;
20pub mod fts_types;
21pub mod functions;
22pub mod optimizer;
23pub mod params;
24pub mod parser;
25pub mod planner;
26pub mod reserved;
27pub mod resolver;
28pub mod temporal;
29pub mod types;
30pub mod types_array;
31pub mod types_expr;
32pub mod visitor;
33
34pub use temporal::{TemporalScope, ValidTime};
35pub use visitor::PlanVisitor;
36pub use visitor::dispatch;
37
38pub use catalog::{SqlCatalog, SqlCatalogError};
39pub use error::{Result, SqlError};
40pub use params::ParamValue;
41pub use types::*;
42
43pub fn parse_expr_string(expr_text: &str) -> Result<SqlExpr> {
48 use sqlparser::dialect::GenericDialect;
49 use sqlparser::parser::Parser;
50
51 let dialect = GenericDialect {};
52 let ast_expr = Parser::new(&dialect)
53 .try_with_sql(expr_text)
54 .map_err(|e| SqlError::Parse {
55 detail: e.to_string(),
56 })?
57 .parse_expr()
58 .map_err(|e| SqlError::Parse {
59 detail: e.to_string(),
60 })?;
61
62 resolver::expr::convert_expr(&ast_expr)
63}
64
65use functions::registry::FunctionRegistry;
66use parser::array_stmt::{ArrayStatement, try_parse_array_statement};
67use parser::preprocess;
68use parser::statement::{StatementKind, classify, parse_sql};
69
70pub fn plan_sql(sql: &str, catalog: &dyn SqlCatalog) -> Result<Vec<SqlPlan>> {
75 if let Some(stmt) = try_parse_array_statement(sql)? {
78 return plan_array_statement(stmt, catalog);
79 }
80 let preprocessed = preprocess::preprocess(sql)?;
81 let effective_sql = preprocessed.as_ref().map_or(sql, |p| p.sql.as_str());
82 let is_upsert = preprocessed.as_ref().is_some_and(|p| p.is_upsert);
83 let temporal = preprocessed
84 .as_ref()
85 .map(|p| p.temporal)
86 .unwrap_or_default();
87
88 let statements = parse_sql(effective_sql)?;
89 plan_statements(&statements, is_upsert, temporal, catalog)
90}
91
92pub fn plan_sql_with_params(
99 sql: &str,
100 params: &[ParamValue],
101 catalog: &dyn SqlCatalog,
102) -> Result<Vec<SqlPlan>> {
103 if let Some(stmt) = try_parse_array_statement(sql)? {
107 let _ = params; return plan_array_statement(stmt, catalog);
109 }
110 let preprocessed = preprocess::preprocess(sql)?;
111 let effective_sql = preprocessed.as_ref().map_or(sql, |p| p.sql.as_str());
112 let is_upsert = preprocessed.as_ref().is_some_and(|p| p.is_upsert);
113 let temporal = preprocessed
114 .as_ref()
115 .map(|p| p.temporal)
116 .unwrap_or_default();
117
118 let mut statements = parse_sql(effective_sql)?;
119 for stmt in &mut statements {
120 params::bind_params(stmt, params);
121 }
122 plan_statements(&statements, is_upsert, temporal, catalog)
123}
124
125fn plan_statements(
127 statements: &[sqlparser::ast::Statement],
128 is_upsert: bool,
129 temporal: TemporalScope,
130 catalog: &dyn SqlCatalog,
131) -> Result<Vec<SqlPlan>> {
132 let functions = FunctionRegistry::new();
133 let mut plans = Vec::new();
134
135 for stmt in statements {
136 match classify(stmt) {
137 StatementKind::Select(query) => {
138 let plan = planner::select::plan_query(query, catalog, &functions, temporal)?;
139 let plan = optimizer::optimize(plan);
140 plans.push(plan);
141 }
142 StatementKind::Insert(ins) => {
143 let mut dml_plans = if is_upsert {
144 planner::dml::plan_upsert(ins, catalog)?
145 } else {
146 planner::dml::plan_insert(ins, catalog)?
147 };
148 plans.append(&mut dml_plans);
149 }
150 StatementKind::Update(stmt) => {
151 let mut update_plans = planner::dml::plan_update(stmt, catalog)?;
152 plans.append(&mut update_plans);
153 }
154 StatementKind::Delete(stmt) => {
155 let mut delete_plans = planner::dml::plan_delete(stmt, catalog)?;
156 plans.append(&mut delete_plans);
157 }
158 StatementKind::Truncate(stmt) => {
159 let mut trunc_plans = planner::dml::plan_truncate_stmt(stmt)?;
160 plans.append(&mut trunc_plans);
161 }
162 StatementKind::Merge(stmt) => {
163 let mut merge_plans = planner::merge::plan_merge(stmt, catalog)?;
164 plans.append(&mut merge_plans);
165 }
166 StatementKind::CreateIndex(ci) => {
167 plans.push(planner::index_ddl::plan_create_index(ci)?);
168 }
169 StatementKind::DropIndex(stmt) => {
170 plans.push(planner::index_ddl::plan_drop_index(stmt)?);
171 }
172 StatementKind::Other => {
173 return Err(SqlError::Unsupported {
174 detail: format!("statement type: {stmt}"),
175 });
176 }
177 }
178 }
179
180 Ok(plans)
181}
182
183fn plan_array_statement(stmt: ArrayStatement, catalog: &dyn SqlCatalog) -> Result<Vec<SqlPlan>> {
185 match stmt {
186 ArrayStatement::Create(c) => Ok(vec![planner::array_ddl::plan_create_array(&c)?]),
187 ArrayStatement::Drop(d) => Ok(vec![planner::array_ddl::plan_drop_array(&d)?]),
188 ArrayStatement::Insert(i) => planner::array_dml::plan_insert_array(&i, catalog),
189 ArrayStatement::Delete(d) => planner::array_dml::plan_delete_array(&d, catalog),
190 ArrayStatement::Alter(a) => Ok(vec![planner::array_ddl::plan_alter_array(&a)?]),
191 }
192}