multisql/executor/alter_row/
validate_unique.rs

1use {
2	crate::{Column, Glue, NullOrd, Result, Row, ValidateError, Value},
3	std::cmp::Ordering,
4};
5
6macro_rules! some_or_continue {
7	($option: expr) => {
8		match $option {
9			Some(value) => value,
10			None => return Some(Ok(())),
11		}
12	};
13}
14macro_rules! some_or {
15	($option: expr, $or: block) => {
16		match $option {
17			Some(value) => value,
18			None => $or,
19		}
20	};
21}
22
23impl Glue {
24	pub(crate) async fn validate_unique(
25		&self,
26		database: &Option<String>,
27		table_name: &str,
28		column_defs: &[Column],
29		rows: &[Row],
30		ignore_keys: Option<&[Value]>,
31	) -> Result<()> {
32		let unique_columns: Vec<usize> = column_defs
33			.iter()
34			.enumerate()
35			.filter_map(|(index, column_def)| {
36				if column_def.is_unique {
37					Some(index)
38				} else {
39					None
40				}
41			})
42			.collect();
43		let mut existing_values: Vec<Vec<Value>> = vec![vec![]; unique_columns.len()];
44		self.get_database(database)?
45			.scan_data(table_name)
46			.await?
47			.into_iter()
48			.try_for_each::<_, Result<_>>(|(key, row)| {
49				if let Some(ignore_keys) = ignore_keys {
50					if ignore_keys.iter().any(|ignore_key| ignore_key == &key) {
51						return Ok(());
52					}
53				}
54				let row = row.0;
55				unique_columns
56					.iter()
57					.enumerate()
58					.map(|(index, row_index)| {
59						existing_values
60							.get_mut(index)?
61							.push(row.get(*row_index)?.clone());
62						Some(())
63					})
64					.collect::<Option<()>>()
65					.ok_or_else(|| ValidateError::UnreachableUniqueValues.into())
66			})?;
67
68		let mut new_values: Vec<Vec<Value>> = vec![vec![]; unique_columns.len()];
69		rows.iter().try_for_each::<_, Result<_>>(|row| {
70			unique_columns
71				.iter()
72				.enumerate()
73				.map(|(index, row_index)| {
74					new_values
75						.get_mut(index)?
76						.push(row.0.get(*row_index)?.clone());
77					Some(())
78				})
79				.collect::<Option<()>>()
80				.ok_or_else(|| ValidateError::UnreachableUniqueValues.into())
81		})?;
82		let mut existing_values_iter = existing_values.into_iter();
83		new_values
84			.into_iter()
85			.map(|mut new_values| {
86				let mut existing_values = existing_values_iter.next()?;
87
88				existing_values.sort_unstable_by(|value_l, value_r| {
89					value_l.partial_cmp(value_r).unwrap_or(Ordering::Equal)
90				});
91				new_values.sort_unstable_by(|value_l, value_r| {
92					value_l.partial_cmp(value_r).unwrap_or(Ordering::Equal)
93				});
94
95				let mut existing_values = existing_values.into_iter();
96				let mut new_values = new_values.into_iter();
97
98				let mut new_value = some_or_continue!(new_values.next());
99				let mut existing_value = some_or!(existing_values.next(), {
100					loop {
101						let new_new = some_or_continue!(new_values.next());
102						if new_new == new_value {
103							return Some(Err(ValidateError::DuplicateEntryOnUniqueField.into()));
104						}
105						new_value = new_new;
106					}
107				});
108
109				loop {
110					match existing_value.null_cmp(&new_value) {
111						Some(Ordering::Equal) => {
112							return Some(Err(ValidateError::DuplicateEntryOnUniqueField.into()))
113						}
114						Some(Ordering::Greater) => {
115							let new_new = some_or_continue!(new_values.next());
116							if new_new == new_value {
117								return Some(
118									Err(ValidateError::DuplicateEntryOnUniqueField.into()),
119								);
120							}
121							new_value = new_new;
122						}
123						Some(Ordering::Less) => {
124							existing_value = some_or!(existing_values.next(), {
125								loop {
126									let new_new = some_or_continue!(new_values.next());
127									if new_new == new_value {
128										return Some(Err(
129											ValidateError::DuplicateEntryOnUniqueField.into(),
130										));
131									}
132									new_value = new_new;
133								}
134							});
135						}
136						None => {
137							let new_new = some_or_continue!(new_values.next());
138							if new_new == new_value {
139								return Some(
140									Err(ValidateError::DuplicateEntryOnUniqueField.into()),
141								);
142							}
143							new_value = new_new;
144							existing_value = some_or!(existing_values.next(), {
145								loop {
146									let new_new = some_or_continue!(new_values.next());
147									if new_new == new_value {
148										return Some(Err(
149											ValidateError::DuplicateEntryOnUniqueField.into(),
150										));
151									}
152									new_value = new_new;
153								}
154							});
155						}
156					}
157				}
158			})
159			.collect::<Option<Result<()>>>()
160			.ok_or(ValidateError::UnreachableUniqueValues)?
161	}
162}