use crate::{
Db, Result,
db::{Connect, Pool, Shared},
engine::Engine,
schema::Register,
};
use toasty_core::{
driver::Driver,
schema::{self, app},
};
use std::sync::Arc;
#[derive(Default)]
pub struct Builder {
models: Vec<app::Model>,
core: schema::Builder,
}
impl Builder {
pub fn register<T: Register>(&mut self) -> &mut Self {
let schema = T::schema();
tracing::debug!(model = %schema.name(), "registering model");
self.models.push(schema);
self
}
pub fn table_name_prefix(&mut self, prefix: &str) -> &mut Self {
self.core.table_name_prefix(prefix);
self
}
pub fn build_app_schema(&self) -> Result<app::Schema> {
app::Schema::from_macro(&self.models)
}
pub async fn connect(&mut self, url: &str) -> Result<Db> {
let con = Connect::new(url).await?;
self.build(con).await
}
pub async fn build(&mut self, driver: impl Driver) -> Result<Db> {
tracing::info!(models = self.models.len(), "building database schema");
let capability = driver.capability();
capability.validate()?;
let schema = self.core.build(self.build_app_schema()?, capability)?;
tracing::info!(tables = schema.db.tables.len(), "schema built successfully");
let engine = Engine::new(Arc::new(schema), capability);
let pool = Pool::new(driver, engine.clone())?;
let shared = Arc::new(Shared { engine, pool });
let conn = shared.pool.get(shared.clone()).await?;
std::mem::drop(conn);
tracing::info!("database ready");
Ok(Db { shared })
}
}