1use rudb_catalog::{Catalog, Entry, QualifiedName, duplicate_check, same_name};
18use rudb_common::bounds::End;
19use rudb_common::{
20 Bound as ColumnBound, Clustering, Error, Field, LogicalType, Result, Session, Stat, Value,
21 Width,
22};
23use rudb_parse::ast::{self, Ast};
24use rudb_parse::{NONE, deparse, parse_ast};
25use rudb_plan::{Arm, Expr, ExprRef, Node, Plan, SortKey};
26
27use crate::binder::Binder;
28use crate::parameters::Parameters;
29
30#[derive(Debug)]
35pub enum Bound {
36 Query(Plan),
38 CreateTable(CreateTable),
40 CreateView(CreateView),
42 DropTable(DropTable),
44 Schema(SchemaChange),
46 Sequence(SequenceChange),
48 Alter(Alter),
50 Insert(Insert),
52 Setting(Setting),
54 Checkpoint,
56 Transaction(ast::Transaction),
58 Explain { plan: Plan, analyze: bool, statistics: bool },
71}
72
73#[derive(Debug)]
85pub struct Setting {
86 pub name: String,
88 pub scope: ast::Scope,
90 pub value: Option<Value>,
92 pub pragma: bool,
94}
95
96#[derive(Debug)]
98pub struct CreateTable {
99 pub name: QualifiedName,
101 pub columns: Vec<Field>,
104 pub source: Option<Plan>,
106 pub if_not_exists: bool,
108 pub or_replace: bool,
110 pub keys: Vec<rudb_catalog::Key>,
112 pub defaults: Vec<Option<String>>,
114 pub sequences: Vec<QualifiedName>,
116 pub checks: Vec<String>,
118 pub foreign: Vec<rudb_catalog::ForeignKey>,
120}
121
122#[derive(Debug)]
129pub struct CreateView {
130 pub name: QualifiedName,
132 pub sql: String,
134 pub statement: String,
139 pub aliases: Vec<String>,
141 pub if_not_exists: bool,
143 pub or_replace: bool,
145 pub columns: Vec<Field>,
151}
152
153#[derive(Debug, Clone, PartialEq, Eq)]
159pub struct SchemaChange {
160 pub catalog: String,
162 pub name: String,
164 pub drop: bool,
166 pub quiet: bool,
168 pub or_replace: bool,
171 pub cascade: bool,
173}
174
175#[derive(Debug, Clone, PartialEq, Eq)]
177pub struct SequenceChange {
178 pub name: Option<QualifiedName>,
180 pub drop: bool,
182 pub if_not_exists: bool,
184 pub or_replace: bool,
186 pub cascade: bool,
188 pub options: rudb_common::sequence::Options,
190 pub owner: Option<QualifiedName>,
193}
194
195#[derive(Debug)]
197pub struct Alter {
198 pub name: Option<QualifiedName>,
200 pub alteration: Option<rudb_catalog::Alteration>,
202 pub rewrite: Option<Plan>,
204}
205
206#[derive(Debug)]
208pub struct DropTable {
209 pub names: Vec<QualifiedName>,
214 pub kind: Entry,
216}
217
218#[derive(Debug)]
220pub struct Insert {
221 pub name: QualifiedName,
223 pub source: Plan,
226 pub write: Write,
228 pub returning: Option<Box<Plan>>,
231 pub conflict: Option<Conflict>,
233 pub checks: Option<Checks>,
235}
236
237#[derive(Debug)]
243pub struct Checks {
244 pub plan: Box<Plan>,
246 pub messages: Vec<String>,
248}
249
250#[derive(Debug)]
252pub struct Conflict {
253 pub key: Option<usize>,
255 pub action: ConflictAction,
257}
258
259#[derive(Debug)]
261pub enum ConflictAction {
262 Nothing,
264 Replace(Vec<usize>),
266 Update {
270 columns: Vec<usize>,
272 plan: Box<Plan>,
274 },
275}
276
277#[derive(Debug, Clone, Copy, PartialEq, Eq)]
279pub enum Write {
280 Append,
282 Update,
285 Delete,
288}
289
290fn returning(
292 ast: &Ast,
293 catalog: &Catalog,
294 parameters: &Parameters,
295 session: &Session,
296 query: Option<ast::QueryRef>,
297) -> Result<Option<Box<Plan>>> {
298 let Some(query) = query else { return Ok(None) };
299 let mut binder = Binder::with(catalog, parameters, session);
300 let (root, _) = binder.bind_query(ast, query)?;
301 Ok(Some(Box::new(finish(binder, root)?)))
302}
303
304pub fn bind_statement(ast: &Ast, catalog: &Catalog) -> Result<Bound> {
311 bind_statement_with(ast, catalog, &Parameters::new(), &Session::new())
312}
313
314pub fn bind_statement_with(
324 ast: &Ast,
325 catalog: &Catalog,
326 parameters: &Parameters,
327 session: &Session,
328) -> Result<Bound> {
329 bind_one(ast, catalog, parameters, session, false)
330}
331
332pub fn bind_statement_outlined(
345 ast: &Ast,
346 catalog: &Catalog,
347 parameters: &Parameters,
348 session: &Session,
349) -> Result<Bound> {
350 bind_one(ast, catalog, parameters, session, true)
351}
352
353fn bind_one(
354 ast: &Ast,
355 catalog: &Catalog,
356 parameters: &Parameters,
357 session: &Session,
358 outlined: bool,
359) -> Result<Bound> {
360 let statement = match ast.statements.as_slice() {
361 [statement] => *statement,
362 [] => return Err(Error::binder("no statement to bind")),
363 _ => return Err(Error::not_implemented("a script of more than one statement")),
364 };
365 match statement {
366 ast::Statement::Query(query) => {
367 let mut binder = Binder::with(catalog, parameters, session);
368 binder.outlined = outlined;
369 let (root, _) = binder.bind_query(ast, query)?;
370 Ok(Bound::Query(finish(binder, root)?))
371 }
372 ast::Statement::CreateTable(index) => {
373 create_table(ast, catalog, parameters, session, index)
374 }
375 ast::Statement::CreateView(index) => create_view(ast, catalog, parameters, session, index),
376 ast::Statement::DropTable(index) => drop_table(ast, catalog, index),
377 ast::Statement::Schema(index) => {
378 let written = ast.schema(index);
379 if written.temporary {
380 return Err(Error::binder("Temporary schemas are not supported"));
381 }
382 let parts: Vec<&str> = ast.name(written.name).collect();
383 let (catalog, name) = catalog.schema_name(&parts)?;
384 Ok(Bound::Schema(SchemaChange {
385 catalog,
386 name,
387 drop: written.drop,
388 quiet: written.quiet,
389 or_replace: written.or_replace,
390 cascade: written.cascade,
391 }))
392 }
393 ast::Statement::Sequence(index) => {
394 let written = ast.sequence(index);
395 let parts: Vec<&str> = ast.name(written.name).collect();
396 let alter = !written.owner.is_empty();
397 let mut owner = None;
398 let name = if written.drop || alter {
399 match catalog.resolve_sequence(&parts) {
400 Ok(name) => Some(name),
401 Err(_) if written.quiet => None,
402 Err(error) => return Err(error),
403 }
404 } else if written.temporary {
405 Some(catalog.resolve_for_create_temporary(&parts)?)
406 } else {
407 Some(catalog.resolve_for_create(&parts)?)
408 };
409 if alter && name.is_some() {
410 let parts: Vec<&str> = ast.name(written.owner).collect();
411 owner = Some(catalog.resolve_owner(&parts)?);
412 }
413 Ok(Bound::Sequence(SequenceChange {
414 name,
415 drop: written.drop,
416 if_not_exists: written.quiet,
417 or_replace: written.or_replace,
418 cascade: written.cascade,
419 options: written.options,
420 owner,
421 }))
422 }
423 ast::Statement::Alter(index) => alter(ast, catalog, parameters, session, index),
424 ast::Statement::Insert(index) => insert(ast, catalog, parameters, session, index),
425 ast::Statement::Update(index) => change(ast, catalog, parameters, session, index, false),
426 ast::Statement::Delete(index) => change(ast, catalog, parameters, session, index, true),
427 ast::Statement::Set(index) | ast::Statement::Reset(index) => {
428 setting(ast, catalog, parameters, session, index)
429 }
430 ast::Statement::Checkpoint => Ok(Bound::Checkpoint),
431 ast::Statement::Transaction(kind) => Ok(Bound::Transaction(kind)),
432 ast::Statement::Explain { query, analyze, statistics } => {
433 let mut binder = Binder::with(catalog, parameters, session);
434 let (root, _) = binder.bind_query(ast, query)?;
435 Ok(Bound::Explain { plan: finish(binder, root)?, analyze, statistics })
436 }
437 }
438}
439
440pub fn bind_statement_sql(sql: &str, catalog: &Catalog) -> Result<Bound> {
446 let ast = parse_ast(sql)?;
447 bind_statement(&ast, catalog)
448}
449
450fn finish(binder: Binder<'_>, root: rudb_plan::NodeRef) -> Result<Plan> {
452 let mut plan = binder.into_plan();
453 plan.set_root(root);
454 plan.validate()?;
455 Ok(plan)
456}
457
458fn create_table(
459 ast: &Ast,
460 catalog: &Catalog,
461 parameters: &Parameters,
462 session: &Session,
463 index: ast::CreateTableRef,
464) -> Result<Bound> {
465 let written = ast.create_table(index);
466 let parts: Vec<&str> = ast.name(written.name).collect();
467 let name = if written.temporary {
468 catalog.resolve_for_create_temporary(&parts)?
469 } else {
470 catalog.resolve_for_create(&parts)?
471 };
472 let defs = ast.column_defs(written.columns);
473 let (mut columns, source) = if written.query == NONE {
474 let mut columns = Vec::with_capacity(defs.len());
475 for def in defs {
476 let text = ast.string(def.ty);
477 if text.is_empty() {
478 return Err(Error::binder(format!(
479 "Column \"{}\" was declared without a type",
480 ast.string(def.name)
481 )));
482 }
483 let ty = LogicalType::parse(text)?;
484 let column = ast.string(def.name);
485 columns.push(if def.not_null {
486 Field::required(column, ty)
487 } else {
488 Field::new(column, ty)
489 });
490 }
491 (columns, None)
492 } else {
493 let mut binder = Binder::with(catalog, parameters, session);
494 let (root, scope) = binder.bind_query(ast, written.query)?;
495 if defs.len() > scope.len() {
496 return Err(Error::binder("Target table has more colum names than query result."));
499 }
500 let mut columns = Vec::with_capacity(scope.columns.len());
501 for (at, column) in scope.columns.iter().enumerate() {
502 let named = match defs.get(at) {
503 Some(def) => ast.string(def.name).to_string(),
504 None => column.name.clone(),
505 };
506 columns.push(Field::new(named, column.ty.clone()));
507 }
508 if defs.is_empty() {
509 deduplicate(&mut columns);
510 }
511 (columns, Some(finish(binder, root)?))
512 };
513 duplicate_check(&columns)?;
514 let mut defaults = Vec::with_capacity(defs.len());
515 let mut sequences = Vec::new();
516 for def in defs {
517 defaults.push(if def.default == NONE {
518 None
519 } else {
520 let (text, used) = default_text(ast, def.default, catalog, parameters, session)?;
521 for name in used {
522 if !sequences.contains(&name) {
523 sequences.push(name);
524 }
525 }
526 Some(text)
527 });
528 }
529 let mut checks = Vec::new();
530 for &expr in ast.expr_list(written.checks) {
531 checks.push(check_text(ast, expr, &columns, catalog, parameters, session)?);
532 }
533 let mut keys = Vec::new();
534 for (at, &names) in ast.name_list(written.keys).iter().enumerate() {
535 let mut places = Vec::new();
536 for wanted in ast.name(names) {
537 let Some(place) = columns.iter().position(|field| same_name(&field.name, wanted))
538 else {
539 return Err(Error::catalog(format!(
540 "table \"{}\" does not have a column named \"{wanted}\"",
541 name.table
542 )));
543 };
544 places.push(place);
545 }
546 let primary = at as u32 == written.primary;
547 if primary {
548 for &place in &places {
549 columns[place].not_null = true;
550 }
551 }
552 keys.push(rudb_catalog::Key { columns: places, primary });
553 }
554 let mut foreign = Vec::new();
555 let lists = ast.name_list(written.foreign).iter();
556 let tables = ast.name_list(written.foreign_tables).iter();
557 let referenced = ast.name_list(written.foreign_referenced).iter();
558 for ((&names, &table), &wanted) in lists.zip(tables).zip(referenced) {
559 let names: Vec<&str> = ast.name(names).collect();
560 let parts: Vec<&str> = ast.name(table).collect();
561 let wanted: Vec<&str> = ast.name(wanted).collect();
562 let key = (names.as_slice(), parts.as_slice(), wanted.as_slice());
563 foreign.push(foreign_key(catalog, &name, (&columns, &keys), key)?);
564 }
565 Ok(Bound::CreateTable(CreateTable {
566 name,
567 columns,
568 source,
569 if_not_exists: written.if_not_exists,
570 or_replace: written.or_replace,
571 keys,
572 defaults,
573 checks,
574 foreign,
575 sequences,
576 }))
577}
578
579fn foreign_key(
585 catalog: &Catalog,
586 made: &QualifiedName,
587 (columns, keys): (&[Field], &[rudb_catalog::Key]),
588 (names, parts, wanted): (&[&str], &[&str], &[&str]),
589) -> Result<rudb_catalog::ForeignKey> {
590 let mut places = Vec::with_capacity(names.len());
591 for &wanted in names {
592 let Some(place) = columns.iter().position(|field| same_name(&field.name, wanted)) else {
593 return Err(Error::binder(format!(
594 "Failed to create foreign key: referencing column \"{wanted}\" does not exist"
595 )));
596 };
597 places.push(place);
598 }
599 let own = parts.last().is_some_and(|last| same_name(last, &made.table))
600 && catalog.resolve(parts).map_or(true, |resolved| resolved == *made);
601 let (table, fields, held): (QualifiedName, Vec<Field>, Vec<rudb_catalog::Key>) = if own {
602 (made.clone(), columns.to_vec(), keys.to_vec())
603 } else {
604 let resolved = catalog.resolve(parts)?;
605 if catalog.view(&resolved).is_ok() {
606 return Err(Error::binder("cannot reference a VIEW with a FOREIGN KEY"));
607 }
608 let table = catalog.table(&resolved)?;
609 (resolved, table.columns().to_vec(), table.keys().to_vec())
610 };
611 let referenced = if wanted.is_empty() {
612 let Some(primary) = held.iter().find(|key| key.primary) else {
613 return Err(Error::binder(format!(
614 "Failed to create foreign key: there is no primary key for referenced table \"{}\"",
615 table.table
616 )));
617 };
618 if primary.columns.len() != places.len() {
619 return Err(Error::parser(
620 "The number of referencing and referenced columns for foreign keys must be the same",
621 ));
622 }
623 primary.columns.clone()
624 } else {
625 let mut referenced = Vec::with_capacity(wanted.len());
626 for &column in wanted {
627 let Some(place) = fields.iter().position(|field| same_name(&field.name, column)) else {
628 return Err(Error::binder(format!(
629 "Failed to create foreign key: referenced table \"{}\" does not have a column \
630 named \"{column}\"",
631 table.table
632 )));
633 };
634 referenced.push(place);
635 }
636 let mut sorted = referenced.clone();
637 sorted.sort_unstable();
638 let matched = held.iter().any(|key| {
639 let mut columns = key.columns.clone();
640 columns.sort_unstable();
641 columns == sorted
642 });
643 if !matched && held.is_empty() {
644 return Err(Error::binder(format!(
645 "Failed to create foreign key: there is no primary key or unique constraint for \
646 referenced table \"{}\"",
647 table.table
648 )));
649 }
650 if !matched {
651 return Err(Error::binder(format!(
652 "Failed to create foreign key: referenced table \"{}\" does not have a primary key \
653 or unique constraint on the columns {}",
654 table.table,
655 wanted.join(", ")
656 )));
657 }
658 referenced
659 };
660 for (&from, &to) in places.iter().zip(&referenced) {
661 if columns[from].ty != fields[to].ty {
662 return Err(Error::binder(format!(
663 "Failed to create foreign key: incompatible types between column \"{}\" (\"{}\") \
664 and column \"{}\" (\"{}\")",
665 fields[to].name, fields[to].ty, columns[from].name, columns[from].ty
666 )));
667 }
668 }
669 Ok(rudb_catalog::ForeignKey { columns: places, table, referenced })
670}
671
672fn check_text(
674 ast: &Ast,
675 expr: ast::ExprRef,
676 columns: &[Field],
677 catalog: &Catalog,
678 parameters: &Parameters,
679 session: &Session,
680) -> Result<String> {
681 if crate::expr::has_aggregate(ast, expr) {
682 return Err(Error::binder("aggregate functions are not allowed in check constraints"));
683 }
684 let mut binder = Binder::with(catalog, parameters, session);
685 let index = binder.fresh_index();
686 let mut scope = crate::scope::Scope::empty();
687 for (at, field) in columns.iter().enumerate() {
688 scope.push(crate::scope::Visible {
689 table: String::new(),
690 name: field.name.clone(),
691 binding: rudb_plan::ColumnBinding::new(index, at as u32),
692 ty: field.ty.clone(),
693 not_null: false,
694 key: None,
695 default: None,
696 qualified: false,
697 also: None,
698 });
699 }
700 match binder.bind_expr(ast, expr, &scope) {
701 Err(error) if error.message().starts_with("Referenced column \"") => {
702 let column = error.message().split('"').nth(1).unwrap_or_default();
703 Err(Error::binder(format!(
704 "Table does not contain column \"{column}\" referenced in check constraint!"
705 )))
706 }
707 Err(error) => Err(error),
708 Ok(_) if !binder.windows.is_empty() => {
709 Err(Error::binder("window functions are not allowed in check constraints"))
710 }
711 Ok(_) => Ok(deparse::expression(ast, expr)),
712 }
713}
714
715fn bind_checks(
718 catalog: &Catalog,
719 parameters: &Parameters,
720 session: &Session,
721 name: &QualifiedName,
722) -> Result<Option<Checks>> {
723 let table = catalog.table(name)?;
724 if table.checks().is_empty() {
725 return Ok(None);
726 }
727 let failed: Vec<String> =
728 table.checks().iter().map(|text| format!("NOT CAST(({text}) AS BOOLEAN)")).collect();
729 let ast = parse_ast(&format!("SELECT {}", failed.join(", ")))?;
730 let ast::Statement::Query(query) = ast.statements[0] else {
731 return Err(Error::internal("a check that is not an expression"));
732 };
733 let ast::QueryBody::Select(select) = ast.query(query).body else {
734 return Err(Error::internal("a check that is not an expression"));
735 };
736 let mut binder = Binder::with(catalog, parameters, session);
737 let (root, scope) =
738 binder.bind_catalog_table(&ast, name, name.table.clone(), ast::Slice::default())?;
739 let mut exprs = Vec::with_capacity(failed.len());
740 let mut names = Vec::with_capacity(failed.len());
741 for target in ast.target_list(ast.select(select).targets) {
742 exprs.push(binder.bind_expr(&ast, target.expr, &scope)?);
743 names.push(binder.plan_mut().intern("failed"));
744 }
745 let exprs = binder.plan_mut().add_expr_list(&exprs);
746 let names = binder.plan_mut().add_name_list(&names);
747 let index = binder.fresh_index();
748 let root = binder.plan_mut().add_node(Node::Project { input: root, index, exprs, names });
749 let messages = table
750 .checks()
751 .iter()
752 .map(|text| {
753 format!(
754 "CHECK constraint failed on table \"{}\" with expression CHECK({text})",
755 name.table
756 )
757 })
758 .collect();
759 Ok(Some(Checks { plan: Box::new(finish(binder, root)?), messages }))
760}
761
762fn default_text(
766 ast: &Ast,
767 expr: ast::ExprRef,
768 catalog: &Catalog,
769 parameters: &Parameters,
770 session: &Session,
771) -> Result<(String, Vec<QualifiedName>)> {
772 if crate::expr::has_aggregate(ast, expr) {
773 return Err(Error::binder("DEFAULT value cannot contain aggregates!"));
774 }
775 let mut binder = Binder::with(catalog, parameters, session);
776 let before = binder.plan_mut().node_count();
777 match binder.bind_expr(ast, expr, &crate::scope::Scope::empty()) {
778 Err(error) if error.message().starts_with("Referenced ") => {
779 Err(Error::binder("DEFAULT value cannot contain column names"))
780 }
781 Err(error) => Err(error),
782 Ok(_) if binder.plan_mut().node_count() > before => {
784 Err(Error::binder("DEFAULT value cannot contain subqueries"))
785 }
786 Ok(_) if !binder.windows.is_empty() => {
787 Err(Error::binder("DEFAULT value cannot contain window functions!"))
788 }
789 Ok(_) => Ok((deparse::expression(ast, expr), binder.sequences)),
790 }
791}
792
793fn alter(
797 ast: &Ast,
798 catalog: &Catalog,
799 parameters: &Parameters,
800 session: &Session,
801 index: ast::AlterRef,
802) -> Result<Bound> {
803 let written = ast.alter(index);
804 let nothing = |name| Ok(Bound::Alter(Alter { name, alteration: None, rewrite: None }));
805 let parts: Vec<&str> = ast.name(written.name).collect();
806 let wanted = if written.view { Entry::View } else { Entry::Table };
807 let name = match catalog.resolve_as(&parts, wanted) {
808 Ok(name) => name,
809 Err(_) if written.quiet => return nothing(None),
810 Err(error) => return Err(error),
811 };
812 let kind = catalog.entry(&name)?;
813 if written.view && kind == Entry::Table {
814 return Err(Error::catalog("Can only modify table with ALTER TABLE statement"));
815 }
816 if let ast::AlterAction::Rename { to } = written.action {
817 let alteration = rudb_catalog::Alteration::Rename(ast.string(to).to_string());
818 return Ok(Bound::Alter(Alter {
819 name: Some(name),
820 alteration: Some(alteration),
821 rewrite: None,
822 }));
823 }
824 if kind == Entry::View {
825 return Err(Error::catalog("Can only modify view with ALTER VIEW statement"));
826 }
827 let table = catalog.table(&name)?;
828 let fields = table.columns();
829 let place = |column: ast::StrRef| {
830 fields.iter().position(|field| same_name(&field.name, ast.string(column)))
831 };
832 let missing = |column: ast::StrRef| {
833 let names: Vec<String> = fields.iter().map(|field| format!("\"{}\"", field.name)).collect();
834 Error::binder(format!(
835 "Table \"{}\" does not have a column with name \"{}\"\n\nDid you mean: {}",
836 name.table,
837 ast.string(column),
838 names.join(", ")
839 ))
840 };
841 let found = |column: ast::StrRef| place(column).ok_or_else(|| missing(column));
842 let checks = table.checks();
843 let mut rewrite = None;
844 let alteration = match written.action {
845 ast::AlterAction::Rename { .. } => unreachable!("a rename is handled above"),
846 ast::AlterAction::RenameColumn { column, to } => {
847 let at = found(column)?;
848 let (old, to) = (fields[at].name.as_str(), ast.string(to));
849 if in_foreign_key(catalog, &name, table, at) {
850 return Err(Error::catalog(format!(
852 "Cannot rename column \"\"{old}\"\" because this is involved in the foreign key \
853 constraint"
854 )));
855 }
856 let checks =
857 checks.iter().map(|text| rename_in(text, old, to)).collect::<Result<Vec<_>>>()?;
858 rudb_catalog::Alteration::RenameColumn { column: at, to: to.to_string(), checks }
859 }
860 ast::AlterAction::AddColumn { column, quiet } => {
861 if quiet && place(column.name).is_some() {
862 return nothing(Some(name));
863 }
864 let ty = LogicalType::parse(ast.string(column.ty))?;
865 let field = Field {
866 not_null: column.not_null,
867 ..Field::new(ast.string(column.name), ty.clone())
868 };
869 let (default, sequences) = if column.default == NONE {
870 (None, Vec::new())
871 } else {
872 let (text, used) = default_text(ast, column.default, catalog, parameters, session)?;
873 (Some(text), used)
874 };
875 rewrite = Some(table_rewrite(
876 ast,
877 (catalog, parameters, session),
878 &name,
879 |binder, _, out| {
880 let value = if column.default == NONE {
881 let null = binder.add_constant(Value::Null);
882 binder.cast_to(null, &ty)
883 } else {
884 let value =
885 binder.bind_expr(ast, column.default, &crate::scope::Scope::empty())?;
886 binder.checked_cast_to(value, &ty, false)?
887 };
888 out.push((value, field.name.clone()));
889 Ok(())
890 },
891 )?);
892 rudb_catalog::Alteration::AddColumn { field, default, sequences }
893 }
894 ast::AlterAction::DropColumn { column, quiet } => {
895 let Some(at) = place(column) else {
896 return if quiet { nothing(Some(name)) } else { Err(missing(column)) };
897 };
898 let dropped = fields[at].name.as_str();
899 let mut kept = Vec::with_capacity(checks.len());
900 for text in checks {
901 let used = columns_in(text)?;
902 if !used.iter().any(|used| same_name(used, dropped)) {
903 kept.push(text.clone());
904 } else if used.iter().any(|used| !same_name(used, dropped)) {
905 return Err(Error::catalog(format!(
906 "Cannot drop column \"{dropped}\" because there is a CHECK constraint that \
907 depends on it"
908 )));
909 }
910 }
911 rewrite =
912 Some(table_rewrite(ast, (catalog, parameters, session), &name, |_, _, out| {
913 out.remove(at);
914 Ok(())
915 })?);
916 rudb_catalog::Alteration::DropColumn { column: at, checks: kept }
917 }
918 ast::AlterAction::Default { column, default } => {
919 let at = found(column)?;
920 let (default, sequences) = if default == NONE {
921 (None, Vec::new())
922 } else {
923 let (text, used) = default_text(ast, default, catalog, parameters, session)?;
924 (Some(text), used)
925 };
926 rudb_catalog::Alteration::Default { column: at, default, sequences }
927 }
928 ast::AlterAction::NotNull { column, set } => {
929 rudb_catalog::Alteration::NotNull { column: found(column)?, set }
930 }
931 ast::AlterAction::Type { column, ty, using } => {
932 let at = found(column)?;
933 let changed = fields[at].name.as_str();
934 if table.keys().iter().any(|key| key.columns.contains(&at)) {
935 return Err(Error::binder(
936 "Cannot change the type of a column that has a UNIQUE or PRIMARY KEY \
937 constraint specified",
938 ));
939 }
940 for text in checks {
941 if columns_in(text)?.iter().any(|used| same_name(used, changed)) {
942 return Err(Error::binder(
943 "Cannot change the type of a column that has a CHECK constraint specified",
944 ));
945 }
946 }
947 if in_foreign_key(catalog, &name, table, at) {
948 return Err(Error::binder(
949 "Cannot change the type of a column that has a FOREIGN KEY constraint specified",
950 ));
951 }
952 let mut target =
953 if ty == NONE { None } else { Some(LogicalType::parse(ast.string(ty))?) };
954 rewrite = Some(table_rewrite(
955 ast,
956 (catalog, parameters, session),
957 &name,
958 |binder, scope, out| {
959 let value = if using == NONE {
960 out[at].0
961 } else {
962 binder.bind_expr(ast, using, scope)?
963 };
964 let ty = target
965 .get_or_insert_with(|| binder.plan_mut().expr_type(value).clone())
966 .clone();
967 out[at].0 = binder.checked_cast_to(value, &ty, false)?;
968 Ok(())
969 },
970 )?);
971 let ty = target.ok_or_else(|| Error::internal("an ALTER TYPE that settled no type"))?;
972 rudb_catalog::Alteration::Type { column: at, ty }
973 }
974 };
975 Ok(Bound::Alter(Alter { name: Some(name), alteration: Some(alteration), rewrite }))
976}
977
978fn in_foreign_key(
981 catalog: &Catalog,
982 name: &QualifiedName,
983 table: &rudb_catalog::Table,
984 at: usize,
985) -> bool {
986 table.foreign().iter().any(|key| key.columns.contains(&at))
987 || catalog.tables().any(|held| {
988 held.foreign().iter().any(|key| key.table == *name && key.referenced.contains(&at))
989 })
990}
991
992fn table_rewrite(
995 ast: &Ast,
996 (catalog, parameters, session): (&Catalog, &Parameters, &Session),
997 name: &QualifiedName,
998 change: impl FnOnce(
999 &mut Binder<'_>,
1000 &crate::scope::Scope,
1001 &mut Vec<(ExprRef, String)>,
1002 ) -> Result<()>,
1003) -> Result<Plan> {
1004 let mut binder = Binder::with(catalog, parameters, session);
1005 let (root, scope) =
1006 binder.bind_catalog_table(ast, name, name.table.clone(), ast::Slice::default())?;
1007 let mut out = Vec::with_capacity(scope.columns.len() + 1);
1008 for column in &scope.columns {
1009 let expr = binder.plan_mut().add_expr(Expr::Column(column.binding), column.ty.clone());
1010 out.push((expr, column.name.clone()));
1011 }
1012 change(&mut binder, &scope, &mut out)?;
1013 let exprs: Vec<ExprRef> = out.iter().map(|(expr, _)| *expr).collect();
1014 let names: Vec<_> = out.iter().map(|(_, name)| binder.plan_mut().intern(name)).collect();
1015 let exprs = binder.plan_mut().add_expr_list(&exprs);
1016 let names = binder.plan_mut().add_name_list(&names);
1017 let index = binder.fresh_index();
1018 let root = binder.plan_mut().add_node(Node::Project { input: root, index, exprs, names });
1019 finish(binder, root)
1020}
1021
1022fn check_ast(text: &str) -> Result<(Ast, ast::ExprRef)> {
1024 let ast = parse_ast(&format!("SELECT {text}"))?;
1025 let found = match ast.statements.first() {
1026 Some(&ast::Statement::Query(query)) => match ast.query(query).body {
1027 ast::QueryBody::Select(select) => {
1028 ast.target_list(ast.select(select).targets).first().map(|target| target.expr)
1029 }
1030 _ => None,
1031 },
1032 _ => None,
1033 };
1034 let expr = found.ok_or_else(|| Error::internal("a check that is not an expression"))?;
1035 Ok((ast, expr))
1036}
1037
1038fn columns_in(text: &str) -> Result<Vec<String>> {
1040 let (ast, _) = check_ast(text)?;
1041 let mut out = Vec::new();
1042 for expr in &ast.exprs {
1043 if let ast::Expr::Column { name } = *expr {
1044 if let Some(last) = ast.name(name).last() {
1045 out.push(last.to_string());
1046 }
1047 }
1048 }
1049 Ok(out)
1050}
1051
1052fn rename_in(text: &str, old: &str, to: &str) -> Result<String> {
1055 let (mut ast, expr) = check_ast(text)?;
1056 let mut renamed = false;
1057 for at in 0..ast.exprs.len() {
1058 let ast::Expr::Column { name } = ast.exprs[at] else { continue };
1059 if name.len == 0 {
1060 continue;
1061 }
1062 let last = (name.start + name.len - 1) as usize;
1063 if same_name(ast.string(ast.parts[last]), old) {
1064 let index = ast.strings.len() as u32;
1065 ast.strings.push(to.to_string());
1066 ast.parts[last] = index;
1067 renamed = true;
1068 }
1069 }
1070 Ok(if renamed { deparse::expression(&ast, expr) } else { text.to_string() })
1071}
1072
1073fn deduplicate(columns: &mut [Field]) {
1086 for at in 0..columns.len() {
1087 let taken = |name: &str, upto: usize, columns: &[Field]| {
1088 columns[..upto].iter().any(|held| same_name(&held.name, name))
1089 };
1090 if !taken(&columns[at].name, at, columns) {
1091 continue;
1092 }
1093 let mut suffix = 1;
1094 let mut candidate = format!("{}_{suffix}", columns[at].name);
1095 while taken(&candidate, at, columns) {
1096 suffix += 1;
1097 candidate = format!("{}_{suffix}", columns[at].name);
1098 }
1099 columns[at].name = candidate;
1100 }
1101}
1102
1103fn create_view(
1110 ast: &Ast,
1111 catalog: &Catalog,
1112 parameters: &Parameters,
1113 session: &Session,
1114 index: ast::CreateViewRef,
1115) -> Result<Bound> {
1116 let written = ast.create_view(index);
1117 let parts: Vec<&str> = ast.name(written.name).collect();
1118 let name = if written.temporary {
1119 catalog.resolve_for_create_temporary(&parts)?
1120 } else {
1121 catalog.resolve_for_create(&parts)?
1122 };
1123 let aliases: Vec<String> = ast.name(written.columns).map(str::to_string).collect();
1124
1125 let mut binder = Binder::with(catalog, parameters, session);
1126 binder.outlined = true;
1129 let (_, mut scope) = binder.bind_query(ast, written.query)?;
1130 if aliases.len() > scope.len() {
1131 return Err(Error::binder("More VIEW aliases than columns in query result"));
1132 }
1133 if !aliases.is_empty() {
1134 let written: Vec<&str> = aliases.iter().map(String::as_str).collect();
1135 scope.rename(&written, "unnamed_subquery")?;
1136 }
1137
1138 Ok(Bound::CreateView(CreateView {
1139 name,
1140 sql: ast.string(written.sql).to_string(),
1141 statement: deparse::create_view(ast, index),
1142 aliases,
1143 if_not_exists: written.if_not_exists,
1144 or_replace: written.or_replace,
1145 columns: scope.fields(),
1146 }))
1147}
1148
1149fn drop_table(ast: &Ast, catalog: &Catalog, index: ast::DropTableRef) -> Result<Bound> {
1150 let written = ast.drop_table(index);
1151 let kind = if written.view { Entry::View } else { Entry::Table };
1152 let mut names = Vec::new();
1153 for &name in ast.name_list(written.names) {
1154 let parts: Vec<&str> = ast.name(name).collect();
1155 match catalog.resolve_as(&parts, kind) {
1158 Ok(resolved) => names.push(resolved),
1159 Err(error) if written.if_exists => drop(error),
1160 Err(error) => return Err(error),
1161 }
1162 }
1163 Ok(Bound::DropTable(DropTable { names, kind }))
1164}
1165
1166fn setting(
1172 ast: &Ast,
1173 catalog: &Catalog,
1174 parameters: &Parameters,
1175 session: &Session,
1176 index: ast::SettingRef,
1177) -> Result<Bound> {
1178 let written = ast.setting(index);
1179 let name = ast.string(written.name).to_string();
1180 let value = if written.value == NONE {
1181 None
1182 } else {
1183 let mut binder = Binder::with(catalog, parameters, session);
1184 let bound = binder.bind_setting_value(ast, written.value)?;
1185 let Expr::Constant(value) = *binder.plan().expr(bound) else {
1186 return Err(Error::not_implemented(format!(
1187 "a value for {name} that is not a constant"
1188 )));
1189 };
1190 Some(binder.plan().value(value).clone())
1191 };
1192 Ok(Bound::Setting(Setting { name, scope: written.scope, value, pragma: written.pragma }))
1193}
1194
1195fn clustered(
1207 binder: &mut Binder<'_>,
1208 input: rudb_plan::NodeRef,
1209 scope: &crate::scope::Scope,
1210 clustering: &Clustering,
1211 targets: &[usize],
1212 fields: &[Field],
1213) -> Result<rudb_plan::NodeRef> {
1214 let mut keys: Vec<SortKey> = Vec::with_capacity(clustering.columns().len());
1215 for (at, &column) in clustering.columns().iter().enumerate() {
1216 let Some(from) = targets.iter().position(|&target| target == column as usize) else {
1217 continue;
1218 };
1219 let source = &scope.columns[from];
1220 let expr = binder.plan_mut().add_expr(Expr::Column(source.binding), source.ty.clone());
1221 let expr = binder.checked_cast_to(expr, &fields[column as usize].ty, false)?;
1226 let expr =
1227 if at == 0 { bucketed(binder, expr, clustering.width(), fields, column) } else { expr };
1228 keys.push(SortKey { expr, descending: false, nulls_first: false });
1229 }
1230 if keys.is_empty() {
1231 return Ok(input);
1232 }
1233 let keys = binder.plan_mut().add_sort_keys(&keys);
1234 Ok(binder.plan_mut().add_node(Node::Sort { input, keys }))
1235}
1236
1237fn fitted(
1251 binder: &Binder<'_>,
1252 scope: &crate::scope::Scope,
1253 clustering: &Clustering,
1254 targets: &[usize],
1255) -> Clustering {
1256 if clustering.width() != Width::Auto {
1257 return clustering.clone();
1258 }
1259 let Some(from) = targets.iter().position(|&target| target == clustering.partition() as usize)
1260 else {
1261 return clustering.fitted(0, 0);
1262 };
1263 let source = &scope.columns[from];
1264 let Some(zones) = binder.plan().sole_zones() else {
1265 return clustering.fitted(0, 0);
1266 };
1267 let Some(at) = zones.column(&source.name) else {
1272 return clustering.fitted(0, 0);
1273 };
1274 let rows = zones.surviving(&[]).unwrap_or(0);
1275 let days = span(&zones.extreme(at, End::Low), &zones.extreme(at, End::High)).unwrap_or(0);
1276 clustering.fitted(rows, days)
1277}
1278
1279fn span(low: &Stat<ColumnBound>, high: &Stat<ColumnBound>) -> Option<u64> {
1285 let (Stat::Known { value: low, .. }, Stat::Known { value: high, .. }) = (low, high) else {
1286 return None;
1287 };
1288 let days = match (low, high) {
1289 (ColumnBound::Int(low), ColumnBound::Int(high)) => high.checked_sub(*low)?,
1291 (
1295 ColumnBound::Scaled { unscaled: low, scale: at },
1296 ColumnBound::Scaled { unscaled: high, scale: to },
1297 ) if at == to => {
1298 let day = 86_400_i128.checked_mul(10_i128.checked_pow(u32::from(*at))?)?;
1299 high.checked_sub(*low)? / day
1300 }
1301 _ => return None,
1302 };
1303 u64::try_from(days).ok()
1304}
1305
1306fn bucketed(
1308 binder: &mut Binder<'_>,
1309 expr: ExprRef,
1310 width: Width,
1311 fields: &[Field],
1312 column: u32,
1313) -> ExprRef {
1314 if width == Width::Exact {
1315 return expr;
1316 }
1317 let unit = binder.plan_mut().add_value(Value::Varchar(width.to_string().to_lowercase()));
1318 let unit = binder.plan_mut().add_expr(Expr::Constant(unit), LogicalType::Varchar);
1319 let args = binder.plan_mut().add_expr_list(&[unit, expr]);
1320 let name = binder.plan_mut().intern("date_trunc");
1321 let ty = fields[column as usize].ty.clone();
1322 binder.plan_mut().add_expr(Expr::Function { name, args }, ty)
1323}
1324
1325fn insert(
1326 ast: &Ast,
1327 catalog: &Catalog,
1328 parameters: &Parameters,
1329 session: &Session,
1330 index: ast::InsertRef,
1331) -> Result<Bound> {
1332 let written = ast.insert(index);
1333 let parts: Vec<&str> = ast.name(written.name).collect();
1334 let name = catalog.resolve(&parts)?;
1335 if catalog.entry(&name)? == Entry::View {
1336 return Err(Error::catalog(format!("{} is not an table", name.table)));
1339 }
1340 let target = catalog.table(&name)?;
1341 let fields: Vec<Field> = target.columns().to_vec();
1342 let clustering = target.clustering().cloned();
1343
1344 let targets: Vec<usize> = if written.columns.is_empty() {
1348 (0..fields.len()).collect()
1349 } else {
1350 let mut targets = Vec::new();
1351 for column in ast.name(written.columns) {
1352 let at = fields.iter().position(|field| same_name(&field.name, column)).ok_or_else(
1353 || {
1354 Error::binder(format!(
1355 "Table \"{}\" does not have a column named \"{column}\"",
1356 name.table
1357 ))
1358 },
1359 )?;
1360 if targets.contains(&at) {
1361 return Err(Error::binder(format!(
1362 "Column \"{column}\" is named twice in the same INSERT"
1363 )));
1364 }
1365 targets.push(at);
1366 }
1367 targets
1368 };
1369
1370 let defaults: Vec<(LogicalType, Option<String>)> = (0..fields.len())
1371 .map(|at| (fields[at].ty.clone(), target.default(at).map(str::to_owned)))
1372 .collect();
1373 let mut binder = Binder::with(catalog, parameters, session);
1374 let (root, scope) = if written.source == NONE {
1375 (binder.plan_mut().add_node(Node::Dummy), crate::scope::Scope::empty())
1378 } else {
1379 if matches!(ast.query(written.source).body, ast::QueryBody::Values(_)) {
1382 binder.insert_defaults = Some(targets.iter().map(|&at| defaults[at].clone()).collect());
1383 }
1384 binder.bind_query(ast, written.source)?
1385 };
1386 let targets = if written.source == NONE { Vec::new() } else { targets };
1387 if scope.len() != targets.len() {
1388 return Err(Error::binder(format!(
1389 "Table \"{}\" has {} columns but {} values were supplied",
1390 name.table,
1391 targets.len(),
1392 scope.len()
1393 )));
1394 }
1395
1396 let root = match &clustering {
1402 None => root,
1403 Some(clustering) => {
1404 let fitted = fitted(&binder, &scope, clustering, &targets);
1409 clustered(&mut binder, root, &scope, &fitted, &targets, &fields)?
1410 }
1411 };
1412
1413 let mut exprs: Vec<ExprRef> = Vec::with_capacity(fields.len());
1417 let mut names = Vec::with_capacity(fields.len());
1418 for (at, field) in fields.iter().enumerate() {
1419 let expr = match targets.iter().position(|&target| target == at) {
1420 Some(from) => {
1421 let column = &scope.columns[from];
1422 let expr =
1423 binder.plan_mut().add_expr(Expr::Column(column.binding), column.ty.clone());
1424 binder.checked_cast_to(expr, &field.ty, false)?
1425 }
1426 None => binder.bind_default(defaults[at].1.as_deref(), &field.ty)?,
1428 };
1429 exprs.push(expr);
1430 let interned = binder.plan_mut().intern(&field.name);
1431 names.push(interned);
1432 }
1433 let exprs = binder.plan_mut().add_expr_list(&exprs);
1434 let names = binder.plan_mut().add_name_list(&names);
1435 let index = binder.fresh_index();
1436 let root = binder.plan_mut().add_node(Node::Project { input: root, index, exprs, names });
1437 let source = finish(binder, root)?;
1438 let returning = returning(ast, catalog, parameters, session, written.returning)?;
1439 let conflict = match written.conflict {
1440 Some(conflict) => {
1441 Some(bind_conflict(ast, catalog, parameters, session, &name, &targets, conflict)?)
1442 }
1443 None => None,
1444 };
1445 let checks = bind_checks(catalog, parameters, session, &name)?;
1446 Ok(Bound::Insert(Insert { name, source, write: Write::Append, returning, conflict, checks }))
1447}
1448
1449fn bind_conflict(
1452 ast: &Ast,
1453 catalog: &Catalog,
1454 parameters: &Parameters,
1455 session: &Session,
1456 name: &QualifiedName,
1457 targets: &[usize],
1458 conflict: ast::Conflict,
1459) -> Result<Conflict> {
1460 let table = catalog.table(name)?;
1461 let fields = table.columns();
1462 let keys = table.keys();
1463 let key = if conflict.target.is_empty() {
1464 if keys.is_empty() {
1465 return Err(Error::binder(
1466 "There are no UNIQUE/PRIMARY KEY constraints that refer to this table, specify ON \
1467 CONFLICT columns manually",
1468 ));
1469 }
1470 match conflict.action {
1471 ast::ConflictAction::Nothing => None,
1472 _ if keys.len() > 1 => {
1473 return Err(Error::binder(
1474 "Conflict target has to be provided for a DO UPDATE operation when the table \
1475 has multiple UNIQUE/PRIMARY KEY constraints",
1476 ));
1477 }
1478 _ => Some(0),
1479 }
1480 } else {
1481 let mut wanted = Vec::new();
1482 for column in ast.name(conflict.target) {
1483 let Some(at) = fields.iter().position(|field| same_name(&field.name, column)) else {
1484 return Err(Error::binder(format!(
1485 "Table \"{}\" does not have a column with name \"{column}\"",
1486 name.table
1487 )));
1488 };
1489 wanted.push(at);
1490 }
1491 wanted.sort_unstable();
1492 wanted.dedup();
1493 let found = keys.iter().position(|key| {
1494 let mut held = key.columns.clone();
1495 held.sort_unstable();
1496 held == wanted
1497 });
1498 let Some(found) = found else {
1499 return Err(Error::binder(
1500 "The specified columns as conflict target are not referenced by a UNIQUE/PRIMARY \
1501 KEY CONSTRAINT or INDEX",
1502 ));
1503 };
1504 Some(found)
1505 };
1506 let action = match conflict.action {
1507 ast::ConflictAction::Nothing => ConflictAction::Nothing,
1508 ast::ConflictAction::Replace => ConflictAction::Replace(targets.to_vec()),
1509 ast::ConflictAction::Update { columns: written, query } => {
1510 let mut columns = Vec::new();
1511 for column in ast.name(written) {
1512 let Some(at) = fields.iter().position(|field| same_name(&field.name, column))
1513 else {
1514 return Err(Error::binder(format!(
1515 "Referenced update column {column} not found in table!"
1516 )));
1517 };
1518 if columns.contains(&at) {
1519 return Err(Error::binder(format!(
1520 "Multiple assignments to same column \"\"{column}\"\""
1521 )));
1522 }
1523 columns.push(at);
1524 }
1525 let mut binder = Binder::with(catalog, parameters, session);
1526 binder.upsert = true;
1527 let (root, scope) = binder.bind_query(ast, query)?;
1528 let mut exprs = Vec::with_capacity(scope.columns.len());
1531 let mut names = Vec::with_capacity(scope.columns.len());
1532 for (at, column) in scope.columns.iter().enumerate() {
1533 let expr =
1534 binder.plan_mut().add_expr(Expr::Column(column.binding), column.ty.clone());
1535 let ty = columns.get(at).map_or(LogicalType::Boolean, |&to| fields[to].ty.clone());
1536 exprs.push(binder.checked_cast_to(expr, &ty, false)?);
1537 names.push(binder.plan_mut().intern(&column.name));
1538 }
1539 let exprs = binder.plan_mut().add_expr_list(&exprs);
1540 let names = binder.plan_mut().add_name_list(&names);
1541 let index = binder.fresh_index();
1542 let root =
1543 binder.plan_mut().add_node(Node::Project { input: root, index, exprs, names });
1544 ConflictAction::Update { columns, plan: Box::new(finish(binder, root)?) }
1545 }
1546 };
1547 Ok(Conflict { key, action })
1548}
1549
1550fn change(
1559 ast: &Ast,
1560 catalog: &Catalog,
1561 parameters: &Parameters,
1562 session: &Session,
1563 index: ast::InsertRef,
1564 delete: bool,
1565) -> Result<Bound> {
1566 let written = ast.insert(index);
1567 let parts: Vec<&str> = ast.name(written.name).collect();
1568 let name = catalog.resolve(&parts)?;
1569 if catalog.entry(&name)? == Entry::View {
1570 return Err(Error::binder(if delete {
1571 "Can only delete from base table"
1572 } else {
1573 "Can only update base table"
1574 }));
1575 }
1576 let fields: Vec<Field> = catalog.table(&name)?.columns().to_vec();
1577 let mut targets: Vec<usize> = Vec::new();
1578 for column in ast.name(written.columns) {
1579 let at =
1580 fields.iter().position(|field| same_name(&field.name, column)).ok_or_else(|| {
1581 Error::binder(format!("Referenced update column {column} not found in table!"))
1582 })?;
1583 if targets.contains(&at) {
1584 return Err(Error::binder(format!(
1585 "Multiple assignments to same column \"\"{column}\"\""
1586 )));
1587 }
1588 targets.push(at);
1589 }
1590
1591 let mut defaulted = vec![false; targets.len()];
1593 if let ast::QueryBody::Select(select) = ast.query(written.source).body {
1594 let items = ast.target_list(ast.select(select).targets);
1595 let first = items.len().saturating_sub(targets.len());
1596 for (at, item) in items[first..].iter().enumerate() {
1597 defaulted[at] = matches!(ast.expr(item.expr), ast::Expr::Default);
1598 }
1599 }
1600 let table = catalog.table(&name)?;
1601 let mut binder = Binder::with(catalog, parameters, session);
1602 binder.default_as_null = defaulted.contains(&true);
1603 let (root, scope) = binder.bind_query(ast, written.source)?;
1604 binder.default_as_null = false;
1605 let width = fields.len();
1606 if scope.len() != width + 1 + targets.len() {
1607 return Err(Error::internal(format!(
1608 "an UPDATE source of {} columns over a table of {width}",
1609 scope.len()
1610 )));
1611 }
1612 let column = |binder: &mut Binder<'_>, at: usize| {
1613 let column = &scope.columns[at];
1614 binder.plan_mut().add_expr(Expr::Column(column.binding), column.ty.clone())
1615 };
1616 let hit = column(&mut binder, width);
1617 let hit = binder.checked_cast_to(hit, &LogicalType::Boolean, false)?;
1618 let mut exprs = Vec::with_capacity(width);
1619 let mut names = Vec::with_capacity(width);
1620 for (at, field) in fields.iter().enumerate() {
1621 let old = column(&mut binder, at);
1622 let expr = match targets.iter().position(|&target| target == at) {
1623 Some(from) => {
1624 let then = if defaulted[from] {
1625 binder.bind_default(table.default(at), &field.ty)?
1626 } else {
1627 let new = column(&mut binder, width + 1 + from);
1628 binder.checked_cast_to(new, &field.ty, false)?
1629 };
1630 let arms = binder.plan_mut().add_arms(&[Arm { when: hit, then }]);
1631 binder
1632 .plan_mut()
1633 .add_expr(Expr::Case { arms, otherwise: Some(old) }, field.ty.clone())
1634 }
1635 None => old,
1636 };
1637 exprs.push(expr);
1638 let interned = binder.plan_mut().intern(&field.name);
1639 names.push(interned);
1640 }
1641 let yes = binder.add_constant(Value::Boolean(true));
1644 let arms = binder.plan_mut().add_arms(&[Arm { when: hit, then: yes }]);
1645 let otherwise = Some(binder.add_constant(Value::Boolean(false)));
1646 exprs.push(binder.plan_mut().add_expr(Expr::Case { arms, otherwise }, LogicalType::Boolean));
1647 let interned = binder.plan_mut().intern("changed");
1648 names.push(interned);
1649 let exprs = binder.plan_mut().add_expr_list(&exprs);
1650 let names = binder.plan_mut().add_name_list(&names);
1651 let index = binder.fresh_index();
1652 let root = binder.plan_mut().add_node(Node::Project { input: root, index, exprs, names });
1653 let source = finish(binder, root)?;
1654 let returning = returning(ast, catalog, parameters, session, written.returning)?;
1655 let write = if delete { Write::Delete } else { Write::Update };
1656 let checks = if delete { None } else { bind_checks(catalog, parameters, session, &name)? };
1657 Ok(Bound::Insert(Insert { name, source, write, returning, conflict: None, checks }))
1658}