toasty_driver_integration_suite/tests/
embed_enum_collection.rs1use crate::helpers::column;
6use crate::prelude::*;
7
8use toasty_core::{schema::db, stmt};
9
10#[derive(Clone, Copy, Debug, PartialEq, toasty::Embed)]
11enum Color {
12 #[column(variant = 1)]
13 Red,
14 #[column(variant = 2)]
15 Green,
16 #[column(variant = 3)]
17 Blue,
18}
19
20#[derive(Debug, toasty::Model)]
21struct Palette {
22 #[key]
23 #[auto]
24 id: uuid::Uuid,
25 colors: Vec<Color>,
26}
27
28#[driver_test(requires(document_collections))]
30pub async fn vec_enum_create_get(t: &mut Test) -> Result<(), BoxError> {
31 let mut db = t.setup_db(models!(Palette)).await;
32
33 let colors = [Color::Red, Color::Blue];
34 let palette = toasty::create!(Palette { colors }).exec(&mut db).await?;
35
36 let reloaded = Palette::get_by_id(&mut db, &palette.id).await?;
37 assert_eq!(reloaded.colors, colors);
38
39 Ok(())
40}
41
42#[driver_test(requires(document_collections))]
46pub async fn vec_enum_contains_and_len(t: &mut Test) -> Result<(), BoxError> {
47 let mut db = t.setup_db(models!(Palette)).await;
48
49 toasty::create!(Palette::[
50 { colors: [Color::Red, Color::Green] },
51 { colors: [Color::Blue] },
52 { colors: [Color::Red, Color::Green, Color::Blue] },
53 ])
54 .exec(&mut db)
55 .await?;
56
57 let reds = Palette::filter(Palette::fields().colors().contains(Color::Red))
58 .exec(&mut db)
59 .await?;
60 assert_eq!(reds.len(), 2);
61
62 let singletons = Palette::filter(Palette::fields().colors().len().eq(1))
63 .exec(&mut db)
64 .await?;
65 assert_eq!(singletons.len(), 1);
66
67 let triples = Palette::filter(Palette::fields().colors().len().eq(3))
68 .exec(&mut db)
69 .await?;
70 assert_eq!(triples.len(), 1);
71
72 Ok(())
73}
74
75#[driver_test(requires(document_collections))]
78pub async fn vec_enum_uses_discriminant_storage(t: &mut Test) -> Result<(), BoxError> {
79 #[derive(Clone, Copy, Debug, PartialEq, toasty::Embed)]
80 #[column(type = u16)]
81 enum SmallColor {
82 #[column(variant = 1)]
83 Red,
84 #[column(variant = 2)]
85 Green,
86 }
87
88 #[derive(Debug, toasty::Model)]
89 struct SmallPalette {
90 #[key]
91 #[auto]
92 id: uuid::Uuid,
93 colors: Vec<SmallColor>,
94 #[column(type = u8)]
95 compact_colors: Vec<SmallColor>,
96 }
97
98 let mut db = t.setup_db(models!(SmallPalette)).await;
99
100 assert_eq!(
101 column_storage_ty(&db, "small_palettes", "colors"),
102 db::Type::list(db::Type::UnsignedInteger(2))
103 );
104 assert_eq!(
105 column_storage_ty(&db, "small_palettes", "compact_colors"),
106 db::Type::list(db::Type::UnsignedInteger(1))
107 );
108
109 let colors_column = db
110 .schema()
111 .db
112 .column(column(&db, "small_palettes", "colors"));
113 assert_eq!(
114 colors_column.ty,
115 stmt::Type::List(Box::new(stmt::Type::U16))
116 );
117 let compact_column = db
118 .schema()
119 .db
120 .column(column(&db, "small_palettes", "compact_colors"));
121 assert_eq!(
122 compact_column.ty,
123 stmt::Type::List(Box::new(stmt::Type::U8))
124 );
125
126 let colors = [SmallColor::Red, SmallColor::Green];
127 let palette = toasty::create!(SmallPalette {
128 colors,
129 compact_colors: colors,
130 })
131 .exec(&mut db)
132 .await?;
133
134 let reloaded = SmallPalette::get_by_id(&mut db, &palette.id).await?;
135 assert_eq!(reloaded.colors, colors);
136 assert_eq!(reloaded.compact_colors, colors);
137
138 Ok(())
139}
140
141#[driver_test]
144pub async fn enum_storage_propagates_through_wrappers(t: &mut Test) -> Result<(), BoxError> {
145 #[derive(Clone, Copy, Debug, PartialEq, toasty::Embed)]
146 #[column(type = u16)]
147 enum Status {
148 #[column(variant = 1)]
149 Draft,
150 #[column(variant = 2)]
151 Published,
152 }
153
154 #[derive(Debug, toasty::Model)]
155 struct WrappedStatus {
156 #[key]
157 #[auto]
158 id: uuid::Uuid,
159 optional: Option<Status>,
160 deferred: toasty::Deferred<Status>,
161 boxed: Box<Status>,
162 arced: std::sync::Arc<Status>,
163 #[column(type = u8)]
164 rced: std::rc::Rc<Status>,
165 }
166
167 let mut db = t.setup_db(models!(WrappedStatus)).await;
168
169 for name in ["optional", "deferred", "boxed", "arced"] {
170 assert_eq!(
171 column_storage_ty(&db, "wrapped_statuses", name),
172 db::Type::UnsignedInteger(2)
173 );
174 }
175 assert_eq!(
176 column_storage_ty(&db, "wrapped_statuses", "rced"),
177 db::Type::UnsignedInteger(1)
178 );
179
180 let wrapped = toasty::create!(WrappedStatus {
181 optional: Some(Status::Draft),
182 deferred: Status::Published,
183 boxed: Status::Draft,
184 arced: Status::Published,
185 rced: Status::Draft,
186 })
187 .exec(&mut db)
188 .await?;
189
190 let reloaded = WrappedStatus::filter_by_id(wrapped.id)
191 .include(WrappedStatus::fields().deferred())
192 .get(&mut db)
193 .await?;
194 assert_eq!(reloaded.optional, Some(Status::Draft));
195 assert_eq!(*reloaded.deferred.get(), Status::Published);
196 assert_eq!(*reloaded.boxed, Status::Draft);
197 assert_eq!(*reloaded.arced, Status::Published);
198 assert_eq!(*reloaded.rced, Status::Draft);
199
200 Ok(())
201}
202
203#[driver_test]
205pub async fn enum_storage_propagates_through_nested_embed(t: &mut Test) {
206 #[derive(Debug, toasty::Embed)]
207 #[column(type = u8)]
208 enum Status {
209 #[column(variant = 1)]
210 Active,
211 #[column(variant = 2)]
212 Archived,
213 }
214
215 #[derive(Debug, toasty::Embed)]
216 struct Metadata {
217 status: Status,
218 }
219
220 #[derive(Debug, toasty::Model)]
221 struct Item {
222 #[key]
223 #[auto]
224 id: uuid::Uuid,
225 metadata: Metadata,
226 }
227
228 let db = t.setup_db(models!(Item)).await;
229 assert_eq!(
230 column_storage_ty(&db, "items", "metadata_status"),
231 db::Type::UnsignedInteger(1)
232 );
233}
234
235#[derive(Clone, Copy, Debug, PartialEq, toasty::Embed)]
236enum Ink {
237 Cyan,
238 Magenta,
239 Yellow,
240}
241
242#[derive(Debug, toasty::Model)]
243struct Printer {
244 #[key]
245 #[auto]
246 id: uuid::Uuid,
247 inks: Vec<Ink>,
248}
249
250#[driver_test(requires(and(native_enum, native_array)))]
252pub async fn native_enum_vec_stores_as_enum_array(t: &mut Test) -> Result<(), BoxError> {
253 let db = t.setup_db(models!(Printer)).await;
254
255 let storage_ty = column_storage_ty(&db, "printers", "inks");
256 let db::Type::List(elem) = &storage_ty else {
257 panic!("expected List(Enum), got {storage_ty:?}")
258 };
259 let db::Type::Enum(type_enum) = &**elem else {
260 panic!("expected List(Enum), got {storage_ty:?}")
261 };
262
263 let variants: Vec<&str> = type_enum.variants.iter().map(|v| v.name.as_str()).collect();
265 assert_eq!(variants, ["cyan", "magenta", "yellow"]);
266
267 Ok(())
268}
269
270#[driver_test(requires(and(native_enum, vec_scalar)))]
273pub async fn native_enum_vec_create_get(t: &mut Test) -> Result<(), BoxError> {
274 let mut db = t.setup_db(models!(Printer)).await;
275
276 let inks = [Ink::Cyan, Ink::Yellow];
277 let printer = toasty::create!(Printer { inks }).exec(&mut db).await?;
278
279 let reloaded = Printer::get_by_id(&mut db, &printer.id).await?;
280 assert_eq!(reloaded.inks, inks);
281
282 Ok(())
283}