use crate::mappings::SQLiteDatatypes; use crate::schemas::entities::{Column, Table}; pub struct ColumnBuilder { name: String, datatype: SQLiteDatatypes, nullable: bool, default: Option, auto_increment: bool, unique: bool, check_constraint: Option, primary_key: bool, } impl ColumnBuilder { pub fn new() -> ColumnBuilder { ColumnBuilder { name: String::new(), datatype: SQLiteDatatypes::Text, nullable: false, default: None, auto_increment: false, unique: false, check_constraint: None, primary_key: false, } } pub fn with_name(mut self, name: String) -> Self { self.name = name; self } pub fn with_datatype(mut self, datatype: SQLiteDatatypes) -> Self { self.datatype = datatype; self } pub fn with_nullable(mut self) -> Self { self.nullable = true; self } pub fn with_default(mut self, default: String) -> Self { self.default = Some(default); self } pub fn with_auto_increment(mut self) -> Self { self.auto_increment = true; self } pub fn with_unique(mut self) -> Self { self.unique = true; self } pub fn with_check_constraint(mut self, constraint: String) -> Self { self.check_constraint = Some(constraint); self } pub fn with_primary_key(mut self) -> Self { self.primary_key = true; self } pub fn build(self) -> Result { if self.auto_increment && self.datatype != SQLiteDatatypes::Integer { return Err("Cannot set AUTO_INCREMENT on non-INTEGER column".to_string()); } Ok(Column { name: self.name, datatype: self.datatype, nullable: self.nullable, default: self.default, auto_increment: self.auto_increment, unique: self.unique, check_constraint: self.check_constraint, primary_key: self.primary_key, }) } } impl Default for ColumnBuilder { fn default() -> Self { Self::new() } } pub struct TableBuilder { name: String, columns: Vec, strict: bool } impl TableBuilder { pub fn new() -> TableBuilder { TableBuilder { name: String::new(), columns: Vec::new(), strict: false, } } pub fn with_name(mut self, name: String) -> Self { self.name = name; self } pub fn with_strict(mut self) -> Self { self.strict = true; self } pub fn with_column(mut self, column: Column) -> Self { self.columns.push(column); self } pub fn build(self) -> Table { Table { name: self.name, columns: self.columns, strict: self.strict } } } impl Default for TableBuilder { fn default() -> Self { Self::new() } } #[cfg(test)] mod test { use crate::mappings::SQLiteDatatypes; use crate::schemas::builders::{ColumnBuilder, TableBuilder}; #[test] fn test_column_builder() { let result = ColumnBuilder::new() .with_name("name".to_string()) .with_datatype(SQLiteDatatypes::Text) .with_nullable() .build(); match result { Ok(column) => { assert_eq!(column.name, String::from("name")); assert_eq!(column.datatype, SQLiteDatatypes::Text); assert_eq!(column.nullable, true); }, Err(_) => { assert!(false, "should not fail"); } } } #[test] fn test_column_builder_should_fail() { let result = ColumnBuilder::new() .with_name("name".to_string()) .with_datatype(SQLiteDatatypes::Blob) .with_auto_increment() .build(); match result { Ok(_) => { assert!(false, "Should not make auto increment with another type than integer") }, Err(_) => { assert!(true); } } } #[test] fn test_table_builder() { let column = ColumnBuilder::new() .with_name("id".to_string()) .with_datatype(SQLiteDatatypes::Integer) .with_auto_increment() .build() .expect("Failed to create id column"); let table = TableBuilder::new() .with_name("my_table".to_string()) .with_column(column.clone()) .build(); assert_eq!(table.name, String::from("my_table")); assert_eq!(*table.columns.first().unwrap(), column); } }