use super::Field;
use crate::{
schema::{
app::ModelId,
db::{ColumnId, TableId},
},
stmt,
};
#[derive(Debug, Clone)]
pub struct Model {
pub id: ModelId,
pub table: TableId,
pub columns: Vec<ColumnId>,
pub fields: Vec<Field>,
pub model_to_table: stmt::ExprRecord,
pub table_to_model: TableToModel,
}
#[derive(Debug, Default, Clone)]
pub struct TableToModel {
expr: stmt::ExprRecord,
}
impl TableToModel {
pub fn new(expr: stmt::ExprRecord) -> TableToModel {
TableToModel { expr }
}
pub fn lower_returning_model(&self) -> stmt::Expr {
self.expr.clone().into()
}
pub fn lower_expr_reference(&self, nesting: usize, index: usize) -> stmt::Expr {
let mut expr = self.expr[index].clone();
let n = nesting;
if n > 0 {
stmt::visit_mut::for_each_expr_mut(&mut expr, |expr| {
if let stmt::Expr::Reference(stmt::ExprReference::Column(expr_column)) = expr {
expr_column.nesting = n;
}
});
}
expr
}
}
impl Model {
pub fn resolve_field_mapping(&self, projection: &stmt::Projection) -> Option<&Field> {
let [first, rest @ ..] = projection.as_slice() else {
return None;
};
let mut current_field = self.fields.get(*first)?;
for step in rest {
match current_field {
Field::Struct(field_struct) => {
current_field = field_struct.fields.get(*step)?;
}
Field::Primitive(_) => {
return None;
}
_ => {
return None;
}
}
}
Some(current_field)
}
}