Skip to main content

toasty_driver_integration_suite/tests/
crud_driver_ops.rs

1use crate::helpers::column;
2use crate::prelude::*;
3
4use toasty_core::{
5    driver::{Operation, Rows},
6    stmt::{Assignment, BinaryOp, Expr, ExprColumn, ExprSet, Source, Statement, Type},
7};
8
9#[driver_test(id(ID))]
10pub async fn basic_crud(test: &mut Test) -> Result<()> {
11    #[derive(Debug, toasty::Model)]
12    struct User {
13        #[key]
14        #[auto]
15        id: ID,
16
17        name: String,
18        age: i32,
19    }
20
21    let mut db = test.setup_db(models!(User)).await;
22
23    // Helper to get the table ID (handles database-specific prefixes automatically)
24    let user_table_id = table_id(&db, "users");
25    let user_id_column = column(&db, "users", "id");
26
27    // Clear any setup operations (from reset_db, etc.)
28    test.log().clear();
29
30    let is_sql = test.capability().sql;
31
32    // ========== CREATE ==========
33    let user = User::create().name("Alice").age(30).exec(&mut db).await?;
34
35    // Check the CREATE operation
36    let (op, resp) = test.log().pop();
37
38    assert_struct!(op, Operation::QuerySql({
39        stmt: Statement::Insert({
40            target: toasty_core::stmt::InsertTarget::Table({
41                table: == user_table_id,
42                columns.len(): 3,
43                columns: == columns(&db, "users", &["id", "name", "age"]),
44            }),
45            source: {
46                body: _,
47            },
48        }),
49        // ret: None,
50    }));
51
52    if driver_test_cfg!(id_u64) && test.capability().returning_from_mutation {
53        assert_struct!(op, Operation::QuerySql({
54            ret: Some([Type::U64]),
55            last_insert_id_hack: None,
56        }));
57
58        let rows = resp.values.collect_as_value().await?;
59
60        // Check response
61        assert_struct!(rows, == [(1u64,)]);
62    } else if driver_test_cfg!(id_u64) {
63        assert_struct!(op, Operation::QuerySql({
64            ret: None,
65            last_insert_id_hack: Some(1),
66        }));
67
68        let rows = resp.values.collect_as_value().await?;
69
70        // Check response
71        assert_struct!(rows, == [(1u64,)]);
72    } else {
73        assert_struct!(op, Operation::QuerySql({
74            ret: None,
75        }));
76
77        // Check response
78        assert_struct!(resp, {
79            values: Rows::Count(1),
80        });
81    }
82
83    let user_id = user.id;
84
85    // ========== READ ==========
86    let fetched = User::get_by_id(&mut db, &user_id).await?;
87    assert_eq!(fetched.name, "Alice");
88    assert_eq!(fetched.age, 30);
89
90    // Check the READ operation
91    let (op, resp) = test.log().pop();
92
93    if is_sql {
94        assert_struct!(op, Operation::QuerySql({
95            stmt: Statement::Query({
96                body: ExprSet::Select({
97                    source: Source::Table({
98                        tables: [== user_table_id, ..],
99                    }),
100                    filter.expr: Some(Expr::BinaryOp({
101                        lhs.as_expr_column_unwrap(): ExprColumn {
102                            nesting: 0,
103                            table: 0,
104                            column: == user_id_column.index,
105                        },
106                        op: BinaryOp::Eq,
107                        rhs: _,
108                    })),
109                }),
110            }),
111            ret: Some(_),
112        }));
113    } else {
114        assert_struct!(op, Operation::GetByKey({
115            table: == user_table_id,
116            keys: _,
117            select.len(): 3,
118        }));
119    }
120
121    assert_struct!(resp.values, Rows::Stream(_));
122
123    // ========== UPDATE ==========
124    User::filter_by_id(user_id)
125        .update()
126        .age(31)
127        .exec(&mut db)
128        .await?;
129
130    // Check the UPDATE operation
131    let (op, resp) = test.log().pop();
132
133    if is_sql {
134        assert_struct!(op, Operation::QuerySql({
135            stmt: Statement::Update({
136                target: toasty_core::stmt::UpdateTarget::Table(== user_table_id),
137                assignments: #{ [2]: Assignment::Set(Expr::Arg({ position: 0 }))},
138                filter.expr: Some(Expr::BinaryOp({
139                    lhs.as_expr_column_unwrap(): ExprColumn {
140                        nesting: 0,
141                        table: 0,
142                        column: == user_id_column.index,
143                    },
144                    op: BinaryOp::Eq,
145                    rhs: _,
146                })),
147            }),
148            params: [{ value: == 31i32 }, ..],
149            ret: None,
150        }));
151    } else {
152        assert_struct!(op, Operation::UpdateByKey({
153            table: == user_table_id,
154            filter: None,
155            keys: _,
156            assignments: #{ [2]: Assignment::Set(== 31i32)},
157            returning: false,
158        }));
159    }
160
161    assert_struct!(resp, {
162        values: Rows::Count(1),
163    });
164
165    // ========== DELETE ==========
166    User::filter_by_id(user_id).delete().exec(&mut db).await?;
167
168    // Check the DELETE operation
169    let (op, resp) = test.log().pop();
170
171    if is_sql {
172        assert_struct!(op, Operation::QuerySql({
173            stmt: Statement::Delete({
174                from: Source::Table({
175                    tables: [== user_table_id, ..],
176                }),
177                filter.expr: Some(Expr::BinaryOp({
178                    lhs.as_expr_column_unwrap(): ExprColumn {
179                        nesting: 0,
180                        table: 0,
181                        column: == user_id_column.index,
182                    },
183                    op: BinaryOp::Eq,
184                    rhs: _,
185                })),
186            }),
187        }));
188    } else {
189        assert_struct!(op, Operation::DeleteByKey({
190            table: == user_table_id,
191            filter: None,
192            keys: _,
193        }));
194    }
195
196    // Check response
197    assert_struct!(resp, {
198        values: Rows::Count(1),
199    });
200
201    // ========== VERIFY LOG IS EMPTY ==========
202    assert!(test.log().is_empty(), "Log should be empty");
203    Ok(())
204}