toasty_core/schema/diff/
column.rs1use super::Context;
2use crate::schema::db;
3
4use hashbrown::{HashMap, HashSet};
5
6pub enum Column<'a> {
10 Add(&'a db::Column),
12 Drop(&'a db::Column),
14 Alter {
16 previous: &'a db::Column,
18 next: &'a db::Column,
20 },
21}
22
23impl<'a> Column<'a> {
24 pub fn diff(cx: &Context<'a>, previous: &'a [db::Column], next: &'a [db::Column]) -> Vec<Self> {
42 fn has_diff(previous: &db::Column, next: &db::Column) -> bool {
43 previous.name != next.name
44 || previous.storage_ty != next.storage_ty
45 || previous.nullable != next.nullable
46 || previous.primary_key != next.primary_key
47 || previous.auto_increment != next.auto_increment
48 || previous.versionable != next.versionable
49 }
50
51 let mut changes = vec![];
52 let mut add_ids: HashSet<_> = next.iter().map(|next| next.id).collect();
53
54 let next_map = HashMap::<&str, &'a db::Column>::from_iter(
55 next.iter().map(|to| (to.name.as_str(), to)),
56 );
57
58 for previous in previous {
59 let next = if let Some(next_id) = cx.rename_hints().get_column(previous.id) {
60 cx.next().column(next_id)
61 } else if let Some(next) = next_map.get(previous.name.as_str()) {
62 next
63 } else {
64 changes.push(Self::Drop(previous));
65 continue;
66 };
67
68 add_ids.remove(&next.id);
69
70 if has_diff(previous, next) {
71 changes.push(Self::Alter { previous, next });
72 }
73 }
74
75 for column_id in add_ids {
76 changes.push(Self::Add(cx.next().column(column_id)));
77 }
78
79 changes
80 }
81}