Skip to main content

rustrails_record/
querying.rs

1use std::collections::HashMap;
2
3use sea_orm::{ColumnTrait, DatabaseConnection, EntityTrait, FromQueryResult, Iterable};
4use serde_json::{Value, json};
5
6use crate::{Record, RecordError, Relation};
7
8/// Sort direction for ordered record queries.
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10pub enum OrderDirection {
11    /// Sort in ascending order.
12    Asc,
13    /// Sort in descending order.
14    Desc,
15}
16
17/// Async query helpers for [`Record`] types. Use `Querying` for the sync API.
18#[allow(async_fn_in_trait, dead_code)]
19pub(crate) trait AsyncQuerying: Record {
20    /// Finds a record by primary key or returns [`RecordError::NotFound`].
21    async fn find(id: i64, db: &DatabaseConnection) -> Result<Self, RecordError>
22    where
23        <Self::Entity as EntityTrait>::Column: ColumnTrait + Iterable,
24    {
25        Self::find_by_id(id, db).await?.ok_or(RecordError::NotFound)
26    }
27
28    /// Finds a record by primary key and returns `None` when missing.
29    async fn find_by_id(id: i64, db: &DatabaseConnection) -> Result<Option<Self>, RecordError>
30    where
31        <Self::Entity as EntityTrait>::Column: ColumnTrait + Iterable,
32    {
33        let mut conditions = HashMap::new();
34        conditions.insert(Self::primary_key_name().to_owned(), json!(id));
35        Self::r#where(conditions).first(db).await
36    }
37
38    /// Finds the first record matching the provided conditions.
39    async fn find_by(
40        conditions: HashMap<String, Value>,
41        db: &DatabaseConnection,
42    ) -> Result<Option<Self>, RecordError>
43    where
44        <Self::Entity as EntityTrait>::Column: ColumnTrait + Iterable,
45    {
46        Self::r#where(conditions).first(db).await
47    }
48
49    /// Finds the first record matching the provided conditions or returns [`RecordError::NotFound`].
50    async fn find_by_bang(
51        conditions: HashMap<String, Value>,
52        db: &DatabaseConnection,
53    ) -> Result<Self, RecordError>
54    where
55        <Self::Entity as EntityTrait>::Column: ColumnTrait + Iterable,
56    {
57        Self::find_by(conditions, db)
58            .await?
59            .ok_or(RecordError::NotFound)
60    }
61
62    /// Returns one record without imposing an explicit order.
63    async fn take(db: &DatabaseConnection) -> Result<Option<Self>, RecordError>
64    where
65        <Self::Entity as EntityTrait>::Column: ColumnTrait + Iterable,
66    {
67        Relation::<Self>::new().first(db).await
68    }
69
70    /// Returns one record without imposing an explicit order or raises when none exist.
71    async fn take_bang(db: &DatabaseConnection) -> Result<Self, RecordError>
72    where
73        <Self::Entity as EntityTrait>::Column: ColumnTrait + Iterable,
74    {
75        Self::take(db).await?.ok_or(RecordError::NotFound)
76    }
77
78    /// Returns the only matching row.
79    async fn sole(db: &DatabaseConnection) -> Result<Self, RecordError>
80    where
81        <Self::Entity as EntityTrait>::Column: ColumnTrait + Iterable,
82    {
83        Relation::<Self>::new().sole(db).await
84    }
85
86    /// Returns the only matching row for the provided conditions.
87    async fn find_sole_by(
88        conditions: HashMap<String, Value>,
89        db: &DatabaseConnection,
90    ) -> Result<Self, RecordError>
91    where
92        <Self::Entity as EntityTrait>::Column: ColumnTrait + Iterable,
93    {
94        Self::r#where(conditions).sole(db).await
95    }
96
97    /// Plucks the requested column from matching rows.
98    async fn pluck(column: &str, db: &DatabaseConnection) -> Result<Vec<Value>, RecordError>
99    where
100        Self: serde::Serialize,
101        <Self::Entity as EntityTrait>::Column: ColumnTrait + Iterable,
102    {
103        Relation::<Self>::new().pluck(column, db).await
104    }
105
106    /// Picks the first value for the requested column.
107    async fn pick(column: &str, db: &DatabaseConnection) -> Result<Option<Value>, RecordError>
108    where
109        Self: serde::Serialize,
110        <Self::Entity as EntityTrait>::Column: ColumnTrait + Iterable,
111    {
112        Relation::<Self>::new().pick(column, db).await
113    }
114
115    /// Returns all primary key values.
116    async fn ids(db: &DatabaseConnection) -> Result<Vec<i64>, RecordError>
117    where
118        Self: serde::Serialize,
119        <Self::Entity as EntityTrait>::Column: ColumnTrait + Iterable,
120    {
121        Relation::<Self>::new().ids(db).await
122    }
123
124    /// Loads all records for the entity.
125    async fn all(db: &DatabaseConnection) -> Result<Vec<Self>, RecordError>
126    where
127        <Self::Entity as EntityTrait>::Column: ColumnTrait + Iterable,
128    {
129        Relation::<Self>::new().load(db).await
130    }
131
132    /// Loads the first record ordered by primary key ascending.
133    async fn first(db: &DatabaseConnection) -> Result<Option<Self>, RecordError>
134    where
135        <Self::Entity as EntityTrait>::Column: ColumnTrait + Iterable,
136    {
137        Self::order(Self::primary_key_name(), OrderDirection::Asc)
138            .first(db)
139            .await
140    }
141
142    /// Loads the last record ordered by primary key descending.
143    async fn last(db: &DatabaseConnection) -> Result<Option<Self>, RecordError>
144    where
145        <Self::Entity as EntityTrait>::Column: ColumnTrait + Iterable,
146    {
147        Self::order(Self::primary_key_name(), OrderDirection::Desc)
148            .first(db)
149            .await
150    }
151
152    /// Counts all rows for the entity.
153    async fn count(db: &DatabaseConnection) -> Result<u64, RecordError>
154    where
155        <Self::Entity as EntityTrait>::Column: ColumnTrait + Iterable,
156        <Self::Entity as EntityTrait>::Model: FromQueryResult + Send + Sync,
157    {
158        Relation::<Self>::new().count(db).await
159    }
160
161    /// Returns `true` when any record matches the provided conditions.
162    async fn exists_with_conditions(
163        conditions: HashMap<String, Value>,
164        db: &DatabaseConnection,
165    ) -> Result<bool, RecordError>
166    where
167        <Self::Entity as EntityTrait>::Column: ColumnTrait + Iterable,
168    {
169        Self::r#where(conditions).exists(db).await
170    }
171
172    /// Returns `true` when any record matches the provided conditions.
173    async fn exists(
174        conditions: HashMap<String, Value>,
175        db: &DatabaseConnection,
176    ) -> Result<bool, RecordError>
177    where
178        <Self::Entity as EntityTrait>::Column: ColumnTrait + Iterable,
179    {
180        Self::exists_with_conditions(conditions, db).await
181    }
182
183    /// Starts a relation scoped by equality conditions.
184    fn r#where(conditions: HashMap<String, Value>) -> Relation<Self> {
185        Relation::new().r#where(conditions)
186    }
187
188    /// Starts a relation scoped by ordering.
189    fn order(column: &str, dir: OrderDirection) -> Relation<Self> {
190        Relation::new().order(column, dir)
191    }
192
193    /// Starts a relation scoped by a limit.
194    fn limit(n: u64) -> Relation<Self> {
195        Relation::new().limit(n)
196    }
197
198    /// Starts a relation scoped by an offset.
199    fn offset(n: u64) -> Relation<Self> {
200        Relation::new().offset(n)
201    }
202}
203
204#[cfg(test)]
205mod tests {
206    use std::collections::HashMap;
207
208    use sea_orm::{ActiveModelTrait, ActiveValue::Set};
209    use serde_json::json;
210
211    use super::{AsyncQuerying, OrderDirection};
212    use crate::{
213        RecordError,
214        base::test_support::{TestUser, seed_users, setup_db, test_user},
215    };
216
217    #[tokio::test]
218    async fn find_returns_matching_record() {
219        let db = setup_db().await;
220        seed_users(&db).await;
221
222        let user = TestUser::find(2, &db)
223            .await
224            .expect("find should return a record");
225
226        assert_eq!(user.name, "Bob");
227    }
228
229    #[tokio::test]
230    async fn find_missing_returns_not_found() {
231        let db = setup_db().await;
232
233        let error = TestUser::find(404, &db)
234            .await
235            .expect_err("missing row should return an error");
236
237        assert!(matches!(error, RecordError::NotFound));
238    }
239
240    #[tokio::test]
241    async fn find_by_id_returns_none_when_missing() {
242        let db = setup_db().await;
243
244        let user = TestUser::find_by_id(404, &db)
245            .await
246            .expect("query should succeed");
247
248        assert!(user.is_none());
249    }
250
251    #[tokio::test]
252    async fn find_by_filters_by_conditions() {
253        let db = setup_db().await;
254        seed_users(&db).await;
255
256        let mut conditions = HashMap::new();
257        conditions.insert("email".to_owned(), json!("carol@example.com"));
258
259        let user = TestUser::find_by(conditions, &db)
260            .await
261            .expect("query should succeed")
262            .expect("row should exist");
263
264        assert_eq!(user.name, "Carol");
265    }
266
267    #[tokio::test]
268    async fn all_returns_every_row() {
269        let db = setup_db().await;
270        seed_users(&db).await;
271
272        let users = TestUser::all(&db).await.expect("all should succeed");
273
274        assert_eq!(users.len(), 3);
275    }
276
277    #[tokio::test]
278    async fn first_returns_lowest_primary_key() {
279        let db = setup_db().await;
280        seed_users(&db).await;
281
282        let user = TestUser::first(&db)
283            .await
284            .expect("query should succeed")
285            .expect("row should exist");
286
287        assert_eq!(user.name, "Alice");
288    }
289
290    #[tokio::test]
291    async fn last_returns_highest_primary_key() {
292        let db = setup_db().await;
293        seed_users(&db).await;
294
295        let user = TestUser::last(&db)
296            .await
297            .expect("query should succeed")
298            .expect("row should exist");
299
300        assert_eq!(user.name, "Carol");
301    }
302
303    #[tokio::test]
304    async fn count_returns_row_total() {
305        let db = setup_db().await;
306        seed_users(&db).await;
307
308        assert_eq!(TestUser::count(&db).await.expect("count should succeed"), 3);
309    }
310
311    #[tokio::test]
312    async fn exists_returns_true_for_matching_conditions() {
313        let db = setup_db().await;
314        seed_users(&db).await;
315
316        let mut conditions = HashMap::new();
317        conditions.insert("name".to_owned(), json!("Bob"));
318
319        assert!(
320            TestUser::exists(conditions, &db)
321                .await
322                .expect("exists should succeed")
323        );
324    }
325
326    #[tokio::test]
327    async fn exists_returns_false_for_missing_conditions() {
328        let db = setup_db().await;
329        seed_users(&db).await;
330
331        let mut conditions = HashMap::new();
332        conditions.insert("name".to_owned(), json!("Nobody"));
333
334        assert!(
335            !TestUser::exists(conditions, &db)
336                .await
337                .expect("exists should succeed")
338        );
339    }
340
341    #[tokio::test]
342    async fn query_builder_helpers_start_relations() {
343        let db = setup_db().await;
344        seed_users(&db).await;
345
346        let ordered = TestUser::order("id", OrderDirection::Desc)
347            .first(&db)
348            .await
349            .expect("query should succeed")
350            .expect("row should exist");
351        let limited = TestUser::limit(2)
352            .load(&db)
353            .await
354            .expect("limit should load");
355        let offset = TestUser::offset(2)
356            .order("id", OrderDirection::Asc)
357            .load(&db)
358            .await
359            .expect("offset should load");
360
361        assert_eq!(ordered.name, "Carol");
362        assert_eq!(limited.len(), 2);
363        assert_eq!(offset.len(), 1);
364        assert_eq!(offset[0].name, "Carol");
365    }
366    #[tokio::test]
367    async fn find_by_id_returns_matching_record_when_present() {
368        let db = setup_db().await;
369        seed_users(&db).await;
370
371        let user = TestUser::find_by_id(3, &db)
372            .await
373            .expect("query should succeed")
374            .expect("row should exist");
375
376        assert_eq!(user.name, "Carol");
377    }
378
379    #[tokio::test]
380    async fn find_by_returns_none_when_no_match_exists() {
381        let db = setup_db().await;
382        seed_users(&db).await;
383
384        let user = TestUser::find_by(
385            HashMap::from([("email".to_owned(), json!("missing@example.com"))]),
386            &db,
387        )
388        .await
389        .expect("query should succeed");
390
391        assert!(user.is_none());
392    }
393
394    #[tokio::test]
395    async fn find_by_with_multiple_conditions_requires_all_matches() {
396        let db = setup_db().await;
397        seed_users(&db).await;
398
399        let user = TestUser::find_by(
400            HashMap::from([
401                ("name".to_owned(), json!("Bob")),
402                ("email".to_owned(), json!("bob@example.com")),
403            ]),
404            &db,
405        )
406        .await
407        .expect("query should succeed")
408        .expect("row should exist");
409
410        assert_eq!(user.id, Some(2));
411    }
412
413    #[tokio::test]
414    async fn all_marks_loaded_rows_persisted() {
415        let db = setup_db().await;
416        seed_users(&db).await;
417
418        let users = TestUser::all(&db).await.expect("all should succeed");
419
420        assert!(
421            users
422                .iter()
423                .all(|user| user.state == crate::RecordState::Persisted)
424        );
425    }
426
427    #[tokio::test]
428    async fn first_returns_none_when_table_is_empty() {
429        let db = setup_db().await;
430
431        let user = TestUser::first(&db).await.expect("query should succeed");
432
433        assert!(user.is_none());
434    }
435
436    #[tokio::test]
437    async fn last_returns_none_when_table_is_empty() {
438        let db = setup_db().await;
439
440        let user = TestUser::last(&db).await.expect("query should succeed");
441
442        assert!(user.is_none());
443    }
444
445    #[tokio::test]
446    async fn count_returns_zero_when_table_is_empty() {
447        let db = setup_db().await;
448
449        assert_eq!(TestUser::count(&db).await.expect("count should succeed"), 0);
450    }
451
452    #[tokio::test]
453    async fn exists_with_empty_conditions_is_false_without_rows() {
454        let db = setup_db().await;
455
456        assert!(
457            !TestUser::exists(HashMap::new(), &db)
458                .await
459                .expect("exists should succeed")
460        );
461    }
462
463    #[tokio::test]
464    async fn exists_with_empty_conditions_is_true_when_rows_exist() {
465        let db = setup_db().await;
466        seed_users(&db).await;
467
468        assert!(
469            TestUser::exists(HashMap::new(), &db)
470                .await
471                .expect("exists should succeed")
472        );
473    }
474
475    #[tokio::test]
476    async fn exists_with_multiple_conditions_requires_all_conditions() {
477        let db = setup_db().await;
478        seed_users(&db).await;
479
480        assert!(
481            !TestUser::exists(
482                HashMap::from([
483                    ("name".to_owned(), json!("Bob")),
484                    ("email".to_owned(), json!("alice@example.com")),
485                ]),
486                &db,
487            )
488            .await
489            .expect("exists should succeed")
490        );
491    }
492
493    #[tokio::test]
494    async fn where_helper_loads_matching_rows() {
495        let db = setup_db().await;
496        seed_users(&db).await;
497
498        let users = TestUser::r#where(HashMap::from([("name".to_owned(), json!("Bob"))]))
499            .load(&db)
500            .await
501            .expect("where relation should load");
502
503        assert_eq!(users.len(), 1);
504        assert_eq!(users[0].email, "bob@example.com");
505    }
506
507    #[tokio::test]
508    async fn where_helper_with_multiple_conditions_loads_match() {
509        let db = setup_db().await;
510        seed_users(&db).await;
511
512        let users = TestUser::r#where(HashMap::from([
513            ("name".to_owned(), json!("Carol")),
514            ("email".to_owned(), json!("carol@example.com")),
515        ]))
516        .load(&db)
517        .await
518        .expect("where relation should load");
519
520        assert_eq!(users.len(), 1);
521        assert_eq!(users[0].id, Some(3));
522    }
523
524    #[tokio::test]
525    async fn where_helper_with_empty_conditions_loads_all_rows() {
526        let db = setup_db().await;
527        seed_users(&db).await;
528
529        let users = TestUser::r#where(HashMap::new())
530            .load(&db)
531            .await
532            .expect("where relation should load");
533
534        assert_eq!(users.len(), 3);
535    }
536
537    #[tokio::test]
538    async fn order_helper_descending_returns_expected_sequence() {
539        let db = setup_db().await;
540        seed_users(&db).await;
541
542        let users = TestUser::order("id", OrderDirection::Desc)
543            .load(&db)
544            .await
545            .expect("ordered relation should load");
546        let names = users.into_iter().map(|user| user.name).collect::<Vec<_>>();
547
548        assert_eq!(names, vec!["Carol", "Bob", "Alice"]);
549    }
550
551    #[tokio::test]
552    async fn order_helper_ascending_returns_expected_sequence() {
553        let db = setup_db().await;
554        seed_users(&db).await;
555
556        let users = TestUser::order("id", OrderDirection::Asc)
557            .load(&db)
558            .await
559            .expect("ordered relation should load");
560        let names = users.into_iter().map(|user| user.name).collect::<Vec<_>>();
561
562        assert_eq!(names, vec!["Alice", "Bob", "Carol"]);
563    }
564
565    #[tokio::test]
566    async fn limit_helper_zero_returns_no_rows() {
567        let db = setup_db().await;
568        seed_users(&db).await;
569
570        let users = TestUser::limit(0)
571            .load(&db)
572            .await
573            .expect("limit should load");
574
575        assert!(users.is_empty());
576    }
577
578    #[tokio::test]
579    async fn limit_helper_can_chain_with_order() {
580        let db = setup_db().await;
581        seed_users(&db).await;
582
583        let users = TestUser::limit(2)
584            .order("id", OrderDirection::Desc)
585            .load(&db)
586            .await
587            .expect("relation should load");
588        let names = users.into_iter().map(|user| user.name).collect::<Vec<_>>();
589
590        assert_eq!(names, vec!["Carol", "Bob"]);
591    }
592
593    #[tokio::test]
594    async fn offset_helper_beyond_row_count_returns_empty() {
595        let db = setup_db().await;
596        seed_users(&db).await;
597
598        let users = TestUser::offset(10)
599            .order("id", OrderDirection::Asc)
600            .load(&db)
601            .await
602            .expect("relation should load");
603
604        assert!(users.is_empty());
605    }
606
607    #[tokio::test]
608    async fn offset_helper_can_chain_with_limit_and_order() {
609        let db = setup_db().await;
610        seed_users(&db).await;
611
612        let users = TestUser::offset(1)
613            .order("id", OrderDirection::Asc)
614            .limit(1)
615            .load(&db)
616            .await
617            .expect("relation should load");
618
619        assert_eq!(users.len(), 1);
620        assert_eq!(users[0].name, "Bob");
621    }
622
623    #[tokio::test]
624    async fn find_by_id_returns_persisted_record() {
625        let db = setup_db().await;
626        seed_users(&db).await;
627
628        let user = TestUser::find_by_id(1, &db)
629            .await
630            .expect("query should succeed")
631            .expect("row should exist");
632
633        assert_eq!(user.state, crate::RecordState::Persisted);
634    }
635
636    #[tokio::test]
637    async fn find_by_bang_returns_matching_record() {
638        let db = setup_db().await;
639        seed_users(&db).await;
640
641        let user = TestUser::find_by_bang(
642            HashMap::from([("email".to_owned(), json!("bob@example.com"))]),
643            &db,
644        )
645        .await
646        .expect("row should exist");
647
648        assert_eq!(user.name, "Bob");
649    }
650
651    #[tokio::test]
652    async fn find_by_bang_returns_not_found_when_missing() {
653        let db = setup_db().await;
654
655        let error = TestUser::find_by_bang(
656            HashMap::from([("email".to_owned(), json!("missing@example.com"))]),
657            &db,
658        )
659        .await
660        .expect_err("missing row should return an error");
661
662        assert!(matches!(error, RecordError::NotFound));
663    }
664
665    #[tokio::test]
666    async fn take_returns_first_available_row_without_order() {
667        let db = setup_db().await;
668        seed_users(&db).await;
669
670        let user = TestUser::take(&db)
671            .await
672            .expect("take should succeed")
673            .expect("row should exist");
674
675        assert_eq!(user.id, Some(1));
676    }
677
678    #[tokio::test]
679    async fn take_returns_none_when_table_is_empty() {
680        let db = setup_db().await;
681
682        let user = TestUser::take(&db).await.expect("take should succeed");
683
684        assert!(user.is_none());
685    }
686
687    #[tokio::test]
688    async fn take_bang_returns_not_found_when_table_is_empty() {
689        let db = setup_db().await;
690
691        let error = TestUser::take_bang(&db)
692            .await
693            .expect_err("empty tables should fail");
694
695        assert!(matches!(error, RecordError::NotFound));
696    }
697
698    #[tokio::test]
699    async fn sole_returns_only_row_when_table_has_one_record() {
700        let db = setup_db().await;
701        test_user::ActiveModel {
702            name: Set("Solo".to_owned()),
703            email: Set("solo@example.com".to_owned()),
704            ..Default::default()
705        }
706        .insert(&db)
707        .await
708        .expect("fixture insert should succeed");
709
710        let user = TestUser::sole(&db)
711            .await
712            .expect("sole should return the row");
713
714        assert_eq!(user.name, "Solo");
715    }
716
717    #[tokio::test]
718    async fn sole_returns_not_found_when_table_is_empty() {
719        let db = setup_db().await;
720
721        let error = TestUser::sole(&db)
722            .await
723            .expect_err("empty tables should fail");
724
725        assert!(matches!(error, RecordError::NotFound));
726    }
727
728    #[tokio::test]
729    async fn sole_returns_exceeded_when_multiple_rows_match() {
730        let db = setup_db().await;
731        seed_users(&db).await;
732
733        let error = TestUser::sole(&db)
734            .await
735            .expect_err("multiple rows should fail sole");
736
737        assert!(matches!(error, RecordError::SoleRecordExceeded));
738    }
739
740    #[tokio::test]
741    async fn find_sole_by_returns_matching_row() {
742        let db = setup_db().await;
743        seed_users(&db).await;
744
745        let user =
746            TestUser::find_sole_by(HashMap::from([("name".to_owned(), json!("Alice"))]), &db)
747                .await
748                .expect("single matching row should exist");
749
750        assert_eq!(user.email, "alice@example.com");
751    }
752
753    #[tokio::test]
754    async fn find_sole_by_returns_exceeded_when_multiple_rows_match() {
755        let db = setup_db().await;
756        seed_users(&db).await;
757        test_user::ActiveModel {
758            name: Set("Bob".to_owned()),
759            email: Set("bobby@example.com".to_owned()),
760            ..Default::default()
761        }
762        .insert(&db)
763        .await
764        .expect("fixture insert should succeed");
765
766        let error = TestUser::find_sole_by(HashMap::from([("name".to_owned(), json!("Bob"))]), &db)
767            .await
768            .expect_err("multiple matches should fail");
769
770        assert!(matches!(error, RecordError::SoleRecordExceeded));
771    }
772
773    #[tokio::test]
774    async fn pluck_returns_requested_column_values() {
775        let db = setup_db().await;
776        seed_users(&db).await;
777
778        let values = TestUser::pluck("name", &db)
779            .await
780            .expect("pluck should succeed");
781
782        assert_eq!(values, vec![json!("Alice"), json!("Bob"), json!("Carol")]);
783    }
784
785    #[tokio::test]
786    async fn pick_returns_first_requested_column_value() {
787        let db = setup_db().await;
788        seed_users(&db).await;
789
790        let value = TestUser::pick("email", &db)
791            .await
792            .expect("pick should succeed");
793
794        assert_eq!(value, Some(json!("alice@example.com")));
795    }
796
797    #[tokio::test]
798    async fn ids_returns_primary_keys() {
799        let db = setup_db().await;
800        seed_users(&db).await;
801
802        let ids = TestUser::ids(&db).await.expect("ids should succeed");
803
804        assert_eq!(ids, vec![1, 2, 3]);
805    }
806
807    #[tokio::test]
808    async fn exists_with_conditions_matches_rows() {
809        let db = setup_db().await;
810        seed_users(&db).await;
811
812        assert!(
813            TestUser::exists_with_conditions(
814                HashMap::from([("name".to_owned(), json!("Carol"))]),
815                &db,
816            )
817            .await
818            .expect("exists_with_conditions should succeed")
819        );
820    }
821
822    #[tokio::test]
823    async fn exists_with_conditions_returns_false_when_missing() {
824        let db = setup_db().await;
825
826        assert!(
827            !TestUser::exists_with_conditions(
828                HashMap::from([("name".to_owned(), json!("Nobody"))]),
829                &db,
830            )
831            .await
832            .expect("exists_with_conditions should succeed")
833        );
834    }
835}