1use rudb_catalog::{Catalog, QualifiedName, duplicate_check, same_name};
18use rudb_common::{Error, Field, LogicalType, Result, Value};
19use rudb_parse::ast::{self, Ast};
20use rudb_parse::{NONE, parse_ast};
21use rudb_plan::{Expr, ExprRef, Node, Plan};
22
23use crate::binder::Binder;
24
25#[derive(Debug)]
30pub enum Bound {
31 Query(Plan),
33 CreateTable(CreateTable),
35 DropTable(DropTable),
37 Insert(Insert),
39}
40
41#[derive(Debug)]
43pub struct CreateTable {
44 pub name: QualifiedName,
46 pub columns: Vec<Field>,
49 pub source: Option<Plan>,
51 pub if_not_exists: bool,
53 pub or_replace: bool,
55}
56
57#[derive(Debug)]
59pub struct DropTable {
60 pub names: Vec<QualifiedName>,
63}
64
65#[derive(Debug)]
67pub struct Insert {
68 pub name: QualifiedName,
70 pub source: Plan,
73}
74
75pub fn bind_statement(ast: &Ast, catalog: &Catalog) -> Result<Bound> {
82 let statement = match ast.statements.as_slice() {
83 [statement] => *statement,
84 [] => return Err(Error::binder("no statement to bind")),
85 _ => return Err(Error::not_implemented("a script of more than one statement")),
86 };
87 match statement {
88 ast::Statement::Query(query) => {
89 let mut binder = Binder::new(catalog);
90 let (root, _) = binder.bind_query(ast, query)?;
91 Ok(Bound::Query(finish(binder, root)?))
92 }
93 ast::Statement::CreateTable(index) => create_table(ast, catalog, index),
94 ast::Statement::DropTable(index) => drop_table(ast, catalog, index),
95 ast::Statement::Insert(index) => insert(ast, catalog, index),
96 }
97}
98
99pub fn bind_statement_sql(sql: &str, catalog: &Catalog) -> Result<Bound> {
105 let ast = parse_ast(sql)?;
106 bind_statement(&ast, catalog)
107}
108
109fn finish(binder: Binder<'_>, root: rudb_plan::NodeRef) -> Result<Plan> {
111 let mut plan = binder.into_plan();
112 plan.set_root(root);
113 plan.validate()?;
114 Ok(plan)
115}
116
117fn create_table(ast: &Ast, catalog: &Catalog, index: ast::CreateTableRef) -> Result<Bound> {
118 let written = ast.create_table(index);
119 if written.temporary {
120 return Err(Error::not_implemented("CREATE TEMPORARY TABLE"));
124 }
125 if written.if_not_exists && written.or_replace {
126 return Err(Error::binder("OR REPLACE cannot be used together with IF NOT EXISTS"));
127 }
128 let parts: Vec<&str> = ast.name(written.name).collect();
129 let name = catalog.resolve_for_create(&parts)?;
130 let defs = ast.column_defs(written.columns);
131 let (columns, source) = if written.query == NONE {
132 let mut columns = Vec::with_capacity(defs.len());
133 for def in defs {
134 let text = ast.string(def.ty);
135 if text.is_empty() {
136 return Err(Error::binder(format!(
137 "Column \"{}\" was declared without a type",
138 ast.string(def.name)
139 )));
140 }
141 let ty = LogicalType::parse(text)?;
142 let column = ast.string(def.name);
143 columns.push(if def.not_null {
144 Field::required(column, ty)
145 } else {
146 Field::new(column, ty)
147 });
148 }
149 (columns, None)
150 } else {
151 let mut binder = Binder::new(catalog);
152 let (root, scope) = binder.bind_query(ast, written.query)?;
153 if defs.len() > scope.len() {
154 return Err(Error::binder("Target table has more colum names than query result."));
157 }
158 let mut columns = Vec::with_capacity(scope.len());
159 for (at, column) in scope.columns.iter().enumerate() {
160 let named = match defs.get(at) {
161 Some(def) => ast.string(def.name).to_string(),
162 None => column.name.clone(),
163 };
164 columns.push(Field::new(named, column.ty.clone()));
165 }
166 if defs.is_empty() {
167 deduplicate(&mut columns);
168 }
169 (columns, Some(finish(binder, root)?))
170 };
171 duplicate_check(&columns)?;
172 Ok(Bound::CreateTable(CreateTable {
173 name,
174 columns,
175 source,
176 if_not_exists: written.if_not_exists,
177 or_replace: written.or_replace,
178 }))
179}
180
181fn deduplicate(columns: &mut [Field]) {
194 for at in 0..columns.len() {
195 let taken = |name: &str, upto: usize, columns: &[Field]| {
196 columns[..upto].iter().any(|held| same_name(&held.name, name))
197 };
198 if !taken(&columns[at].name, at, columns) {
199 continue;
200 }
201 let mut suffix = 1;
202 let mut candidate = format!("{}_{suffix}", columns[at].name);
203 while taken(&candidate, at, columns) {
204 suffix += 1;
205 candidate = format!("{}_{suffix}", columns[at].name);
206 }
207 columns[at].name = candidate;
208 }
209}
210
211fn drop_table(ast: &Ast, catalog: &Catalog, index: ast::DropTableRef) -> Result<Bound> {
212 let written = ast.drop_table(index);
213 let mut names = Vec::new();
214 for &name in ast.name_list(written.names) {
215 let parts: Vec<&str> = ast.name(name).collect();
216 match catalog.resolve(&parts) {
217 Ok(resolved) => names.push(resolved),
218 Err(error) if written.if_exists => drop(error),
219 Err(error) => return Err(error),
220 }
221 }
222 Ok(Bound::DropTable(DropTable { names }))
223}
224
225fn insert(ast: &Ast, catalog: &Catalog, index: ast::InsertRef) -> Result<Bound> {
226 let written = ast.insert(index);
227 let parts: Vec<&str> = ast.name(written.name).collect();
228 let name = catalog.resolve(&parts)?;
229 let fields: Vec<Field> = catalog.table(&name)?.columns().to_vec();
230
231 let targets: Vec<usize> = if written.columns.is_empty() {
235 (0..fields.len()).collect()
236 } else {
237 let mut targets = Vec::new();
238 for column in ast.name(written.columns) {
239 let at = fields.iter().position(|field| same_name(&field.name, column)).ok_or_else(
240 || {
241 Error::binder(format!(
242 "Table \"{}\" does not have a column named \"{column}\"",
243 name.table
244 ))
245 },
246 )?;
247 if targets.contains(&at) {
248 return Err(Error::binder(format!(
249 "Column \"{column}\" is named twice in the same INSERT"
250 )));
251 }
252 targets.push(at);
253 }
254 targets
255 };
256
257 let mut binder = Binder::new(catalog);
258 let (root, scope) = binder.bind_query(ast, written.source)?;
259 if scope.len() != targets.len() {
260 return Err(Error::binder(format!(
261 "Table \"{}\" has {} columns but {} values were supplied",
262 name.table,
263 targets.len(),
264 scope.len()
265 )));
266 }
267
268 let mut exprs: Vec<ExprRef> = Vec::with_capacity(fields.len());
272 let mut names = Vec::with_capacity(fields.len());
273 for (at, field) in fields.iter().enumerate() {
274 let expr = match targets.iter().position(|&target| target == at) {
275 Some(from) => {
276 let column = &scope.columns[from];
277 let expr =
278 binder.plan_mut().add_expr(Expr::Column(column.binding), column.ty.clone());
279 binder.cast_to(expr, &field.ty)
280 }
281 None => {
282 let value = binder.plan_mut().add_value(Value::Null);
285 binder.plan_mut().add_expr(Expr::Constant(value), field.ty.clone())
286 }
287 };
288 exprs.push(expr);
289 let interned = binder.plan_mut().intern(&field.name);
290 names.push(interned);
291 }
292 let exprs = binder.plan_mut().add_expr_list(&exprs);
293 let names = binder.plan_mut().add_name_list(&names);
294 let index = binder.fresh_index();
295 let root = binder.plan_mut().add_node(Node::Project { input: root, index, exprs, names });
296 Ok(Bound::Insert(Insert { name, source: finish(binder, root)? }))
297}