toasty_core/schema/
builder.rs1mod table;
2
3use super::{app, db, mapping, Result};
4use crate::schema::mapping::TableToModel;
5use crate::schema::{Mapping, Schema, Table, TableId};
6use crate::{driver, stmt};
7use indexmap::IndexMap;
8
9#[derive(Debug)]
10pub struct Builder {
11 table_name_prefix: Option<String>,
13}
14
15struct BuildSchema<'a> {
17 builder: &'a Builder,
19
20 db: &'a driver::Capability,
21
22 table_lookup: IndexMap<String, TableId>,
25
26 tables: Vec<Table>,
28
29 mapping: Mapping,
31}
32
33impl Builder {
34 pub fn new() -> Self {
35 Self {
36 table_name_prefix: None,
37 }
38 }
39
40 pub fn table_name_prefix(&mut self, prefix: &str) -> &mut Self {
41 self.table_name_prefix = Some(prefix.to_string());
42 self
43 }
44
45 pub fn build(&self, mut app: app::Schema, db: &driver::Capability) -> Result<Schema> {
46 let mut builder = BuildSchema {
47 builder: self,
48 db,
49 table_lookup: IndexMap::new(),
50 tables: vec![],
51 mapping: Mapping {
52 models: IndexMap::new(),
53 },
54 };
55
56 for model in app.models.values_mut() {
57 model.verify(db)?;
60
61 builder.build_model_constraints(model)?;
64 }
65
66 for model in app.models() {
70 let app::Model::Root(model) = model else {
72 continue;
73 };
74
75 let table = builder.build_table_stub_for_model(model);
76
77 builder.mapping.models.insert(
79 model.id,
80 mapping::Model {
81 id: model.id,
82 table,
83 columns: vec![],
84 fields: vec![], model_to_table: stmt::ExprRecord::default(),
86 table_to_model: TableToModel::default(),
87 },
88 );
89 }
90
91 builder.build_tables_from_models(&app, db)?;
92
93 let schema = Schema {
94 app,
95 db: db::Schema {
96 tables: builder.tables,
97 },
98 mapping: builder.mapping,
99 };
100
101 schema.verify()?;
103
104 Ok(schema)
105 }
106}
107
108impl Default for Builder {
109 fn default() -> Self {
110 Self::new()
111 }
112}
113
114impl BuildSchema<'_> {
115 fn build_model_constraints(&self, model: &mut app::Model) -> Result<()> {
116 let fields = match model {
117 app::Model::Root(root) => &mut root.fields[..],
118 app::Model::EmbeddedStruct(embedded) => &mut embedded.fields[..],
119 app::Model::EmbeddedEnum(_) => return Ok(()),
120 };
121 for field in fields.iter_mut() {
122 if let app::FieldTy::Primitive(primitive) = &mut field.ty {
123 let storage_ty = db::Type::from_app(
124 &primitive.ty,
125 primitive.storage_ty.as_ref(),
126 &self.db.storage_types,
127 )?;
128
129 if let db::Type::VarChar(size) = storage_ty {
130 field
131 .constraints
132 .push(app::Constraint::length_less_than(size));
133 }
134 }
135 }
136
137 Ok(())
138 }
139}