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;
24use crate::parameters::Parameters;
25
26#[derive(Debug)]
31pub enum Bound {
32 Query(Plan),
34 CreateTable(CreateTable),
36 DropTable(DropTable),
38 Insert(Insert),
40}
41
42#[derive(Debug)]
44pub struct CreateTable {
45 pub name: QualifiedName,
47 pub columns: Vec<Field>,
50 pub source: Option<Plan>,
52 pub if_not_exists: bool,
54 pub or_replace: bool,
56}
57
58#[derive(Debug)]
60pub struct DropTable {
61 pub names: Vec<QualifiedName>,
64}
65
66#[derive(Debug)]
68pub struct Insert {
69 pub name: QualifiedName,
71 pub source: Plan,
74}
75
76pub fn bind_statement(ast: &Ast, catalog: &Catalog) -> Result<Bound> {
83 bind_statement_with(ast, catalog, &Parameters::new())
84}
85
86pub fn bind_statement_with(ast: &Ast, catalog: &Catalog, parameters: &Parameters) -> Result<Bound> {
96 let statement = match ast.statements.as_slice() {
97 [statement] => *statement,
98 [] => return Err(Error::binder("no statement to bind")),
99 _ => return Err(Error::not_implemented("a script of more than one statement")),
100 };
101 match statement {
102 ast::Statement::Query(query) => {
103 let mut binder = Binder::with(catalog, parameters);
104 let (root, _) = binder.bind_query(ast, query)?;
105 Ok(Bound::Query(finish(binder, root)?))
106 }
107 ast::Statement::CreateTable(index) => create_table(ast, catalog, parameters, index),
108 ast::Statement::DropTable(index) => drop_table(ast, catalog, index),
109 ast::Statement::Insert(index) => insert(ast, catalog, parameters, index),
110 }
111}
112
113pub fn bind_statement_sql(sql: &str, catalog: &Catalog) -> Result<Bound> {
119 let ast = parse_ast(sql)?;
120 bind_statement(&ast, catalog)
121}
122
123fn finish(binder: Binder<'_>, root: rudb_plan::NodeRef) -> Result<Plan> {
125 let mut plan = binder.into_plan();
126 plan.set_root(root);
127 plan.validate()?;
128 Ok(plan)
129}
130
131fn create_table(
132 ast: &Ast,
133 catalog: &Catalog,
134 parameters: &Parameters,
135 index: ast::CreateTableRef,
136) -> Result<Bound> {
137 let written = ast.create_table(index);
138 if written.temporary {
139 return Err(Error::not_implemented("CREATE TEMPORARY TABLE"));
143 }
144 if written.if_not_exists && written.or_replace {
145 return Err(Error::binder("OR REPLACE cannot be used together with IF NOT EXISTS"));
146 }
147 let parts: Vec<&str> = ast.name(written.name).collect();
148 let name = catalog.resolve_for_create(&parts)?;
149 let defs = ast.column_defs(written.columns);
150 let (columns, source) = if written.query == NONE {
151 let mut columns = Vec::with_capacity(defs.len());
152 for def in defs {
153 let text = ast.string(def.ty);
154 if text.is_empty() {
155 return Err(Error::binder(format!(
156 "Column \"{}\" was declared without a type",
157 ast.string(def.name)
158 )));
159 }
160 let ty = LogicalType::parse(text)?;
161 let column = ast.string(def.name);
162 columns.push(if def.not_null {
163 Field::required(column, ty)
164 } else {
165 Field::new(column, ty)
166 });
167 }
168 (columns, None)
169 } else {
170 let mut binder = Binder::with(catalog, parameters);
171 let (root, scope) = binder.bind_query(ast, written.query)?;
172 if defs.len() > scope.len() {
173 return Err(Error::binder("Target table has more colum names than query result."));
176 }
177 let mut columns = Vec::with_capacity(scope.len());
178 for (at, column) in scope.columns.iter().enumerate() {
179 let named = match defs.get(at) {
180 Some(def) => ast.string(def.name).to_string(),
181 None => column.name.clone(),
182 };
183 columns.push(Field::new(named, column.ty.clone()));
184 }
185 if defs.is_empty() {
186 deduplicate(&mut columns);
187 }
188 (columns, Some(finish(binder, root)?))
189 };
190 duplicate_check(&columns)?;
191 Ok(Bound::CreateTable(CreateTable {
192 name,
193 columns,
194 source,
195 if_not_exists: written.if_not_exists,
196 or_replace: written.or_replace,
197 }))
198}
199
200fn deduplicate(columns: &mut [Field]) {
213 for at in 0..columns.len() {
214 let taken = |name: &str, upto: usize, columns: &[Field]| {
215 columns[..upto].iter().any(|held| same_name(&held.name, name))
216 };
217 if !taken(&columns[at].name, at, columns) {
218 continue;
219 }
220 let mut suffix = 1;
221 let mut candidate = format!("{}_{suffix}", columns[at].name);
222 while taken(&candidate, at, columns) {
223 suffix += 1;
224 candidate = format!("{}_{suffix}", columns[at].name);
225 }
226 columns[at].name = candidate;
227 }
228}
229
230fn drop_table(ast: &Ast, catalog: &Catalog, index: ast::DropTableRef) -> Result<Bound> {
231 let written = ast.drop_table(index);
232 let mut names = Vec::new();
233 for &name in ast.name_list(written.names) {
234 let parts: Vec<&str> = ast.name(name).collect();
235 match catalog.resolve(&parts) {
236 Ok(resolved) => names.push(resolved),
237 Err(error) if written.if_exists => drop(error),
238 Err(error) => return Err(error),
239 }
240 }
241 Ok(Bound::DropTable(DropTable { names }))
242}
243
244fn insert(
245 ast: &Ast,
246 catalog: &Catalog,
247 parameters: &Parameters,
248 index: ast::InsertRef,
249) -> Result<Bound> {
250 let written = ast.insert(index);
251 let parts: Vec<&str> = ast.name(written.name).collect();
252 let name = catalog.resolve(&parts)?;
253 let fields: Vec<Field> = catalog.table(&name)?.columns().to_vec();
254
255 let targets: Vec<usize> = if written.columns.is_empty() {
259 (0..fields.len()).collect()
260 } else {
261 let mut targets = Vec::new();
262 for column in ast.name(written.columns) {
263 let at = fields.iter().position(|field| same_name(&field.name, column)).ok_or_else(
264 || {
265 Error::binder(format!(
266 "Table \"{}\" does not have a column named \"{column}\"",
267 name.table
268 ))
269 },
270 )?;
271 if targets.contains(&at) {
272 return Err(Error::binder(format!(
273 "Column \"{column}\" is named twice in the same INSERT"
274 )));
275 }
276 targets.push(at);
277 }
278 targets
279 };
280
281 let mut binder = Binder::with(catalog, parameters);
282 let (root, scope) = binder.bind_query(ast, written.source)?;
283 if scope.len() != targets.len() {
284 return Err(Error::binder(format!(
285 "Table \"{}\" has {} columns but {} values were supplied",
286 name.table,
287 targets.len(),
288 scope.len()
289 )));
290 }
291
292 let mut exprs: Vec<ExprRef> = Vec::with_capacity(fields.len());
296 let mut names = Vec::with_capacity(fields.len());
297 for (at, field) in fields.iter().enumerate() {
298 let expr = match targets.iter().position(|&target| target == at) {
299 Some(from) => {
300 let column = &scope.columns[from];
301 let expr =
302 binder.plan_mut().add_expr(Expr::Column(column.binding), column.ty.clone());
303 binder.cast_to(expr, &field.ty)
304 }
305 None => {
306 let value = binder.plan_mut().add_value(Value::Null);
309 binder.plan_mut().add_expr(Expr::Constant(value), field.ty.clone())
310 }
311 };
312 exprs.push(expr);
313 let interned = binder.plan_mut().intern(&field.name);
314 names.push(interned);
315 }
316 let exprs = binder.plan_mut().add_expr_list(&exprs);
317 let names = binder.plan_mut().add_name_list(&names);
318 let index = binder.fresh_index();
319 let root = binder.plan_mut().add_node(Node::Project { input: root, index, exprs, names });
320 Ok(Bound::Insert(Insert { name, source: finish(binder, root)? }))
321}