toasty_core/schema/diff/
indices.rs1use super::Context;
2use crate::schema::db::Index;
3
4use hashbrown::{HashMap, HashSet};
5use std::ops::Deref;
6
7pub struct Indices<'a> {
25 items: Vec<IndicesItem<'a>>,
26}
27
28impl<'a> Indices<'a> {
29 pub fn from(cx: &Context<'a>, previous: &'a [Index], next: &'a [Index]) -> Self {
36 fn has_diff(cx: &Context<'_>, previous: &Index, next: &Index) -> bool {
37 if previous.name != next.name
38 || previous.columns.len() != next.columns.len()
39 || previous.unique != next.unique
40 || previous.primary_key != next.primary_key
41 {
42 return true;
43 }
44
45 for (previous_col, next_col) in previous.columns.iter().zip(next.columns.iter()) {
46 if previous_col.op != next_col.op || previous_col.scope != next_col.scope {
47 return true;
48 }
49
50 let columns_match =
51 if let Some(renamed_to) = cx.rename_hints().get_column(previous_col.column) {
52 renamed_to == next_col.column
53 } else {
54 let previous_column = cx.previous().column(previous_col.column);
55 let next_column = cx.next().column(next_col.column);
56 previous_column.name == next_column.name
57 };
58
59 if !columns_match {
60 return true;
61 }
62 }
63
64 false
65 }
66
67 let mut items = vec![];
68 let mut create_ids: HashSet<_> = next.iter().map(|to| to.id).collect();
69
70 let next_map =
71 HashMap::<&str, &'a Index>::from_iter(next.iter().map(|to| (to.name.as_str(), to)));
72
73 for previous in previous {
74 let next = if let Some(next_id) = cx.rename_hints().get_index(previous.id) {
75 cx.next().index(next_id)
76 } else if let Some(next) = next_map.get(previous.name.as_str()) {
77 next
78 } else {
79 items.push(IndicesItem::DropIndex(previous));
80 continue;
81 };
82
83 create_ids.remove(&next.id);
84
85 if has_diff(cx, previous, next) {
86 items.push(IndicesItem::AlterIndex { previous, next });
87 }
88 }
89
90 for index_id in create_ids {
91 items.push(IndicesItem::CreateIndex(cx.next().index(index_id)));
92 }
93
94 Self { items }
95 }
96
97 pub const fn is_empty(&self) -> bool {
99 self.items.is_empty()
100 }
101}
102
103impl<'a> Deref for Indices<'a> {
104 type Target = Vec<IndicesItem<'a>>;
105
106 fn deref(&self) -> &Self::Target {
107 &self.items
108 }
109}
110
111pub enum IndicesItem<'a> {
113 CreateIndex(&'a Index),
115 DropIndex(&'a Index),
117 AlterIndex {
119 previous: &'a Index,
121 next: &'a Index,
123 },
124}