toasty_driver_integration_suite/tests/
relation_preload_options.rs1use crate::prelude::*;
2
3#[driver_test(
5 requires(sql),
6 scenario(crate::scenarios::has_many_belongs_to_with_flags)
7)]
8pub async fn preload_has_many_ordered_per_parent(test: &mut Test) -> Result<()> {
9 let mut db = setup(test).await;
10
11 toasty::create!(User::[
12 {
13 name: "alice",
14 todos: [
15 { title: "b", complete: false, priority: 2 },
16 { title: "a", complete: false, priority: 2 },
17 { title: "c", complete: false, priority: 1 },
18 ]
19 },
20 {
21 name: "bob",
22 todos: [
23 { title: "z", complete: false, priority: 1 },
24 { title: "y", complete: false, priority: 1 },
25 { title: "x", complete: false, priority: 3 },
26 ]
27 },
28 ])
29 .exec(&mut db)
30 .await?;
31
32 let tuple_ordered: Vec<User> = User::all()
33 .order_by(User::fields().name().asc())
34 .include(User::fields().todos().order_by((
35 Todo::fields().priority().desc(),
36 Todo::fields().title().asc(),
37 )))
38 .exec(&mut db)
39 .await?;
40
41 assert_struct!(tuple_ordered, [
42 { name: "alice", todos.get(): [{ title: "a" }, { title: "b" }, { title: "c" }] },
43 { name: "bob", todos.get(): [{ title: "x" }, { title: "y" }, { title: "z" }] },
44 ]);
45
46 let chained_ordered: Vec<User> = User::all()
47 .order_by(User::fields().name().asc())
48 .include(
49 User::fields()
50 .todos()
51 .order_by(Todo::fields().priority().desc())
52 .order_by(Todo::fields().title().asc()),
53 )
54 .exec(&mut db)
55 .await?;
56
57 assert_struct!(chained_ordered, [
58 { name: "alice", todos.get(): [{ title: "a" }, { title: "b" }, { title: "c" }] },
59 { name: "bob", todos.get(): [{ title: "x" }, { title: "y" }, { title: "z" }] },
60 ]);
61
62 Ok(())
63}
64
65#[driver_test(
67 requires(sql),
68 scenario(crate::scenarios::has_many_belongs_to::id_uuid)
69)]
70pub async fn preload_has_many_filter_and_order(test: &mut Test) -> Result<()> {
71 let mut db = setup(test).await;
72
73 let user = toasty::create!(User {
74 name: "alice",
75 todos: [{ title: "a" }, { title: "c" }, { title: "b" }]
76 })
77 .exec(&mut db)
78 .await?;
79
80 let loaded = User::filter_by_id(user.id)
81 .include(
82 User::fields()
83 .todos()
84 .filter(Todo::fields().title().ne("c"))
85 .order_by(Todo::fields().title().desc()),
86 )
87 .get(&mut db)
88 .await?;
89
90 assert_struct!(loaded.todos.get(), [
91 { title: "b" },
92 { title: "a" },
93 ]);
94
95 Ok(())
96}
97
98#[driver_test(requires(sql), scenario(crate::scenarios::user_post_comment))]
100pub async fn preload_nested_relations_ordered_at_each_level(test: &mut Test) -> Result<()> {
101 let mut db = setup(test).await;
102
103 let user = toasty::create!(User {
104 name: "alice",
105 posts: [
106 {
107 title: "b",
108 comments: [{ body: "a" }, { body: "c" }, { body: "b" }]
109 },
110 {
111 title: "a",
112 comments: [{ body: "x" }, { body: "z" }, { body: "y" }]
113 },
114 ]
115 })
116 .exec(&mut db)
117 .await?;
118
119 let loaded = User::filter_by_id(user.id)
120 .include(
121 User::fields()
122 .posts()
123 .order_by(Post::fields().title().asc()),
124 )
125 .include(
126 User::fields()
127 .posts()
128 .comments()
129 .order_by(Comment::fields().body().desc()),
130 )
131 .get(&mut db)
132 .await?;
133
134 assert_struct!(loaded.posts.get(), [
135 { title: "a", comments.get(): [{ body: "z" }, { body: "y" }, { body: "x" }] },
136 { title: "b", comments.get(): [{ body: "c" }, { body: "b" }, { body: "a" }] },
137 ]);
138
139 Ok(())
140}
141
142#[driver_test(requires(sql))]
144pub async fn preload_modifiers_with_reserved_field_names(test: &mut Test) -> Result<()> {
145 #[derive(Debug, toasty::Model)]
146 struct Parent {
147 #[key]
148 #[auto]
149 id: uuid::Uuid,
150
151 #[has_many]
152 children: toasty::Deferred<Vec<Child>>,
153 }
154
155 #[derive(Debug, toasty::Model)]
156 struct Child {
157 #[key]
158 #[auto]
159 id: uuid::Uuid,
160
161 filter: String,
162 order_by: String,
163 rank: i64,
164
165 #[index]
166 parent_id: uuid::Uuid,
167
168 #[belongs_to(key = parent_id, references = id)]
169 parent: toasty::Deferred<Parent>,
170 }
171
172 let mut db = test.setup_db(models!(Parent, Child)).await;
173
174 let parent = toasty::create!(Parent {
175 children: [
176 { filter: "a", order_by: "a", rank: 1 },
177 { filter: "b", order_by: "b", rank: 3 },
178 { filter: "c", order_by: "c", rank: 2 },
179 ]
180 })
181 .exec(&mut db)
182 .await?;
183
184 let parent = Parent::filter_by_id(parent.id)
185 .include(
186 Parent::fields()
187 .children()
188 .filter(Child::fields().rank().gt(1))
189 .order_by(Child::fields().rank().desc()),
190 )
191 .get(&mut db)
192 .await?;
193
194 assert_struct!(parent.children.get(), [
195 { rank: 3 },
196 { rank: 2 },
197 ]);
198
199 Ok(())
200}
201
202#[driver_test(
204 requires(sql),
205 scenario(crate::scenarios::has_many_belongs_to::id_uuid)
206)]
207pub async fn preload_has_many_repeated_ordering_last_wins(test: &mut Test) -> Result<()> {
208 use toasty_core::{driver::Operation, stmt::Statement};
209
210 let mut db = setup(test).await;
211
212 let user = toasty::create!(User {
213 name: "alice",
214 todos: [{ title: "a" }, { title: "c" }, { title: "b" }]
215 })
216 .exec(&mut db)
217 .await?;
218
219 let loaded = User::filter_by_id(user.id)
220 .include(
221 User::fields()
222 .todos()
223 .order_by(Todo::fields().title().asc()),
224 )
225 .include(
226 User::fields()
227 .todos()
228 .order_by(Todo::fields().title().desc()),
229 )
230 .get(&mut db)
231 .await?;
232
233 assert_struct!(loaded.todos.get(), [
234 { title: "c" },
235 { title: "b" },
236 { title: "a" },
237 ]);
238
239 test.log().clear();
240
241 let loaded = User::filter_by_id(user.id)
242 .include(
243 User::fields()
244 .todos()
245 .order_by(Todo::fields().title().desc()),
246 )
247 .include(User::fields().todos())
248 .get(&mut db)
249 .await?;
250
251 assert_eq!(loaded.todos.get().len(), 3);
252
253 let _ = test.log().pop_last_op(); assert_struct!(test.log().pop_last_op(), Operation::QuerySql({
255 stmt: Statement::Query({ order_by: None }),
256 }));
257
258 Ok(())
259}
260
261#[driver_test(scenario(crate::scenarios::has_one_optional_belongs_to::id_uuid))]
263pub async fn preload_has_one_ordering_rejected(test: &mut Test) -> Result<()> {
264 let mut db = setup(test).await;
265
266 let err = assert_err!(
267 User::all()
268 .include(
269 User::fields()
270 .profile()
271 .order_by(Profile::fields().bio().asc()),
272 )
273 .exec(&mut db)
274 .await
275 );
276
277 assert!(err.is_invalid_statement(), "unexpected error: {err}");
278
279 Ok(())
280}