1use alloc::vec;
4use alloc::vec::Vec;
5use core::fmt::Debug;
6
7use crate::{DynTable, builders::operation::Indirect, encoding::Value};
8
9#[derive(Debug, Clone)]
10pub struct ChangeDelete<T: DynTable, S: AsRef<str>, B: AsRef<[u8]>> {
14 pub(crate) table: T,
15 pub(crate) values: Vec<Value<S, B>>,
17 pub(crate) indirect: bool,
19}
20
21impl<T: DynTable + PartialEq, S: PartialEq + AsRef<str>, B: PartialEq + AsRef<[u8]>> PartialEq
22 for ChangeDelete<T, S, B>
23{
24 fn eq(&self, other: &Self) -> bool {
25 self.table == other.table && self.values == other.values && self.indirect == other.indirect
26 }
27}
28
29impl<T: DynTable + Eq, S: Eq + AsRef<str>, B: Eq + AsRef<[u8]>> Eq for ChangeDelete<T, S, B> {}
30
31impl<T: DynTable, S: AsRef<str>, B: AsRef<[u8]>> AsRef<T> for ChangeDelete<T, S, B> {
32 #[inline]
33 fn as_ref(&self) -> &T {
34 &self.table
35 }
36}
37
38impl<T: DynTable, S: Default + Clone + AsRef<str>, B: Default + Clone + AsRef<[u8]>> From<T>
39 for ChangeDelete<T, S, B>
40{
41 #[inline]
42 fn from(table: T) -> Self {
43 let num_cols = table.number_of_columns();
44 Self {
45 table,
46 values: vec![Value::Null; num_cols],
47 indirect: false,
48 }
49 }
50}
51
52impl<T: DynTable, S: AsRef<str>, B: AsRef<[u8]>> ChangeDelete<T, S, B> {
53 pub fn set(
65 mut self,
66 col_idx: usize,
67 value: impl Into<Value<S, B>>,
68 ) -> Result<Self, crate::errors::Error> {
69 if col_idx >= self.values.len() {
70 return Err(crate::errors::Error::ColumnIndexOutOfBounds(
71 col_idx,
72 self.values.len(),
73 ));
74 }
75 self.values[col_idx] = value.into();
76 Ok(self)
77 }
78
79 #[inline]
101 pub fn set_null(self, col_idx: usize) -> Result<Self, crate::errors::Error>
102 where
103 S: Default,
104 B: Default,
105 {
106 self.set(col_idx, Value::Null)
107 }
108
109 #[inline]
111 pub(crate) fn into_values(self) -> Vec<Value<S, B>> {
112 self.values
113 }
114}
115
116impl<T: DynTable, S: AsRef<str>, B: AsRef<[u8]>> Indirect for ChangeDelete<T, S, B> {
117 #[inline]
118 fn indirect(mut self, indirect: bool) -> Self {
119 self.indirect = indirect;
120 self
121 }
122}
123
124#[derive(Debug, Clone, PartialEq, Eq)]
129pub struct PatchDelete<T: DynTable, S: AsRef<str>, B: AsRef<[u8]>> {
130 pub(crate) table: T,
131 pub(crate) pk: Vec<Value<S, B>>,
133 pub(crate) indirect: bool,
135}
136
137impl<T: DynTable, S: AsRef<str>, B: AsRef<[u8]>> AsRef<T> for PatchDelete<T, S, B> {
138 #[inline]
139 fn as_ref(&self) -> &T {
140 &self.table
141 }
142}
143
144impl<T: DynTable, S: AsRef<str>, B: AsRef<[u8]>> PatchDelete<T, S, B> {
145 #[inline]
151 pub fn new(table: T, pk: Vec<Value<S, B>>) -> Self {
152 Self {
153 table,
154 pk,
155 indirect: false,
156 }
157 }
158}
159
160impl<T: DynTable, S: AsRef<str>, B: AsRef<[u8]>> Indirect for PatchDelete<T, S, B> {
161 #[inline]
162 fn indirect(mut self, indirect: bool) -> Self {
163 self.indirect = indirect;
164 self
165 }
166}
167
168#[cfg(test)]
169mod tests {
170 use super::{ChangeDelete, PatchDelete};
171 use crate::DynTable;
172 use crate::encoding::Value;
173 use crate::errors::Error;
174 use crate::schema::SimpleTable;
175 use alloc::string::String;
176 use alloc::vec;
177 use alloc::vec::Vec;
178
179 fn users() -> SimpleTable {
180 SimpleTable::new("users", &["id", "name"], &[0])
181 }
182
183 #[test]
184 fn test_change_delete_set_out_of_bounds() {
185 let err = ChangeDelete::<_, String, Vec<u8>>::from(users())
186 .set(5, 1i64)
187 .unwrap_err();
188 assert!(
189 matches!(err, Error::ColumnIndexOutOfBounds(5, 2)),
190 "got {err:?}"
191 );
192 }
193
194 #[test]
195 fn test_change_delete_set_null_out_of_bounds() {
196 let err = ChangeDelete::<_, String, Vec<u8>>::from(users())
197 .set_null(2)
198 .unwrap_err();
199 assert!(
200 matches!(err, Error::ColumnIndexOutOfBounds(2, 2)),
201 "got {err:?}"
202 );
203 }
204
205 #[test]
206 fn test_patch_delete_as_ref_returns_table() {
207 let table = users();
208 let delete: PatchDelete<_, String, Vec<u8>> =
209 PatchDelete::new(table.clone(), vec![Value::Integer(1)]);
210 let t: &SimpleTable = delete.as_ref();
211 assert_eq!(t.name(), "users");
212 }
213
214 #[test]
215 fn test_change_delete_eq() {
216 let a = ChangeDelete::<_, String, Vec<u8>>::from(users())
217 .set(0, 1i64)
218 .unwrap();
219 let b = ChangeDelete::<_, String, Vec<u8>>::from(users())
220 .set(0, 1i64)
221 .unwrap();
222 assert_eq!(a, b);
223
224 let c = ChangeDelete::<_, String, Vec<u8>>::from(users())
225 .set(0, 2i64)
226 .unwrap();
227 assert_ne!(a, c);
228 }
229}