use super::{Column, DbProvider, Relation};
use serde::{Deserialize, Serialize};
use welds::detect::{ColumnDef, DataType, TableDef};
use welds::model_traits::TableIdent;
#[derive(Debug, Eq, PartialEq, Serialize, Deserialize, Clone)]
pub struct Table {
pub schema: Option<String>, pub name: String, pub manual_update: bool, model: Option<String>, pub r#type: String, pub columns: Vec<Column>, pub belongs_to: Vec<Relation>, pub has_many: Vec<Relation>, pub database: DbProvider, }
fn type_str(ty: DataType) -> &'static str {
match ty {
DataType::View => "view",
DataType::Table => "table",
}
}
impl Table {
pub fn new(table_def: &TableDef, provider: DbProvider) -> Self {
let mut t = Table {
manual_update: false,
name: table_def.ident().name().to_string(),
schema: table_def.ident().schema().map(|s| s.to_string()),
model: None,
columns: vec![],
r#type: type_str(table_def.ty()).to_string(),
belongs_to: table_def.belongs_to().iter().map(|x| x.into()).collect(),
has_many: table_def.has_many().iter().map(|x| x.into()).collect(),
database: provider,
};
t.update_cols_from(table_def.columns());
t
}
pub fn update_from(&mut self, table_def: &TableDef, provider: DbProvider) {
if self.manual_update {
return;
}
self.name = table_def.ident().name().to_string();
self.schema = table_def.ident().schema().map(|s| s.to_string());
self.r#type = type_str(table_def.ty()).to_string();
self.belongs_to = table_def.belongs_to().iter().map(|x| x.into()).collect();
self.has_many = table_def.has_many().iter().map(|x| x.into()).collect();
self.update_cols_from(table_def.columns());
self.database = provider;
}
fn update_cols_from(&mut self, cols: &[ColumnDef]) {
let col_names: Vec<&str> = cols.iter().map(|x| x.name()).collect();
self.columns
.retain(|c| col_names.contains(&c.db_name.as_str()));
let mut to_add = Vec::default();
for col in cols {
let existing = self.columns.iter_mut().find(|c| c.db_name == col.name());
match existing {
Some(existing) => existing.update_from(col),
None => to_add.push(Column::new(col)),
}
}
self.columns.append(&mut to_add);
}
pub fn module_name(&self) -> String {
use inflector::Inflector;
let start = match &self.model {
Some(s) => s.to_string(),
None => self.name.to_singular(),
};
start.to_snake_case()
}
pub fn struct_name(&self) -> String {
use inflector::Inflector;
let start = match &self.model {
Some(s) => s.to_string(),
None => self.name.to_singular(),
};
start.to_class_case()
}
pub(crate) fn ident(&self) -> TableIdent {
TableIdent::new(&self.name, self.schema.as_ref())
}
}