use super::{Column, Context, Index};
use crate::schema::db;
use hashbrown::{HashMap, HashSet};
pub enum Table<'a> {
Create(&'a db::Table),
Drop(&'a db::Table),
Alter {
previous: &'a db::Table,
next: &'a db::Table,
columns: Vec<Column<'a>>,
indices: Vec<Index<'a>>,
},
}
impl<'a> Table<'a> {
pub fn diff(cx: &Context<'a>, previous: &'a [db::Table], next: &'a [db::Table]) -> Vec<Self> {
let mut changes = vec![];
let mut create_ids: HashSet<_> = next.iter().map(|next| next.id).collect();
let next_map = HashMap::<&str, &'a db::Table>::from_iter(
next.iter().map(|next| (next.name.as_str(), next)),
);
for previous in previous {
let next = if let Some(next_id) = cx.rename_hints().get_table(previous.id) {
cx.next().table(next_id)
} else if let Some(to) = next_map.get(previous.name.as_str()) {
to
} else {
changes.push(Self::Drop(previous));
continue;
};
create_ids.remove(&next.id);
let columns = Column::diff(cx, &previous.columns, &next.columns);
let indices = Index::diff(cx, &previous.indices, &next.indices);
if previous.name != next.name || !columns.is_empty() || !indices.is_empty() {
changes.push(Self::Alter {
previous,
next,
columns,
indices,
});
}
}
for table_id in create_ids {
changes.push(Self::Create(cx.next().table(table_id)));
}
changes
}
}