sqlite_diff_rs/builders/
insert_operation.rs1use alloc::vec;
4use alloc::vec::Vec;
5use core::fmt::Debug;
6
7use crate::{DynTable, SchemaWithPK, builders::operation::Indirect, encoding::Value};
8
9#[derive(Debug)]
10pub struct Insert<T: DynTable, S, B> {
12 table: T,
14 pub(super) values: Vec<Value<S, B>>,
16 pub(crate) indirect: bool,
18}
19
20impl<T: DynTable, S: Clone, B: Clone> Clone for Insert<T, S, B> {
21 fn clone(&self) -> Self {
22 Self {
23 table: self.table.clone(),
24 values: self.values.clone(),
25 indirect: self.indirect,
26 }
27 }
28}
29
30impl<T: SchemaWithPK, S: Clone, B: Clone> Insert<T, S, B> {
31 #[inline]
33 pub fn extract_pk(&self) -> Vec<Value<S, B>> {
34 self.table.extract_pk(&self.values)
35 }
36}
37
38impl<T: DynTable + PartialEq, S: PartialEq + AsRef<str>, B: PartialEq + AsRef<[u8]>> PartialEq
39 for Insert<T, S, B>
40{
41 fn eq(&self, other: &Self) -> bool {
42 self.table == other.table && self.values == other.values && self.indirect == other.indirect
43 }
44}
45
46impl<T: DynTable + Eq, S: Eq + AsRef<str>, B: Eq + AsRef<[u8]>> Eq for Insert<T, S, B> {}
47
48impl<T: DynTable, S: Clone, B: Clone> From<T> for Insert<T, S, B> {
49 #[inline]
50 fn from(table: T) -> Self {
51 let num_cols = table.number_of_columns();
52 Self {
53 table,
54 values: vec![Value::Null; num_cols],
55 indirect: false,
56 }
57 }
58}
59
60impl<T: DynTable, S: AsRef<str>, B: AsRef<[u8]>> AsRef<T> for Insert<T, S, B> {
61 #[inline]
62 fn as_ref(&self) -> &T {
63 &self.table
64 }
65}
66
67impl<T: DynTable, S: AsRef<str>, B: AsRef<[u8]>> Insert<T, S, B> {
68 #[inline]
70 pub(crate) fn into_values(self) -> Vec<Value<S, B>> {
71 self.values
72 }
73
74 pub fn set(
86 mut self,
87 col_idx: usize,
88 value: impl Into<Value<S, B>>,
89 ) -> Result<Self, crate::errors::Error> {
90 if col_idx >= self.values.len() {
91 return Err(crate::errors::Error::ColumnIndexOutOfBounds(
92 col_idx,
93 self.values.len(),
94 ));
95 }
96
97 self.values[col_idx] = value.into();
98 Ok(self)
99 }
100
101 pub fn set_null(self, col_idx: usize) -> Result<Self, crate::errors::Error>
124 where
125 S: Default,
126 B: Default,
127 {
128 self.set(col_idx, Value::Null)
129 }
130}
131
132impl<T: DynTable, S, B> Indirect for Insert<T, S, B> {
133 #[inline]
134 fn indirect(mut self, indirect: bool) -> Self {
135 self.indirect = indirect;
136 self
137 }
138}
139
140#[cfg(test)]
141mod tests {
142 use super::Insert;
143 use crate::errors::Error;
144 use crate::schema::SimpleTable;
145 use alloc::string::String;
146 use alloc::vec::Vec;
147
148 fn users() -> SimpleTable {
149 SimpleTable::new("users", &["id", "name"], &[0])
150 }
151
152 #[test]
153 fn test_insert_set_out_of_bounds() {
154 let err = Insert::<_, String, Vec<u8>>::from(users())
155 .set(99, 1i64)
156 .unwrap_err();
157 assert!(
158 matches!(err, Error::ColumnIndexOutOfBounds(99, 2)),
159 "got {err:?}"
160 );
161 }
162
163 #[test]
164 fn test_insert_set_null_out_of_bounds() {
165 let err = Insert::<_, String, Vec<u8>>::from(users())
166 .set_null(2)
167 .unwrap_err();
168 assert!(
169 matches!(err, Error::ColumnIndexOutOfBounds(2, 2)),
170 "got {err:?}"
171 );
172 }
173
174 #[test]
175 fn test_insert_clone_and_eq() {
176 let a = Insert::<_, String, Vec<u8>>::from(users())
177 .set(0, 1i64)
178 .unwrap();
179 let b = a.clone();
180 assert_eq!(a, b);
181
182 let c = Insert::<_, String, Vec<u8>>::from(users())
183 .set(0, 2i64)
184 .unwrap();
185 assert_ne!(a, c);
186 }
187}