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(== 31)},
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            ret: None,
149        }));
150    } else {
151        assert_struct!(op, Operation::UpdateByKey({
152            table: == user_table_id,
153            filter: None,
154            keys: _,
155            assignments: #{ [2]: Assignment::Set(== 31)},
156            returning: false,
157        }));
158    }
159
160    assert_struct!(resp, {
161        values: Rows::Count(1),
162    });
163
164    // ========== DELETE ==========
165    User::filter_by_id(user_id).delete().exec(&mut db).await?;
166
167    // Check the DELETE operation
168    let (op, resp) = test.log().pop();
169
170    if is_sql {
171        assert_struct!(op, Operation::QuerySql({
172            stmt: Statement::Delete({
173                from: Source::Table({
174                    tables: [== user_table_id, ..],
175                }),
176                filter.expr: Some(Expr::BinaryOp({
177                    lhs.as_expr_column_unwrap(): ExprColumn {
178                        nesting: 0,
179                        table: 0,
180                        column: == user_id_column.index,
181                    },
182                    op: BinaryOp::Eq,
183                    rhs: _,
184                })),
185            }),
186        }));
187    } else {
188        assert_struct!(op, Operation::DeleteByKey({
189            table: == user_table_id,
190            filter: None,
191            keys: _,
192        }));
193    }
194
195    // Check response
196    assert_struct!(resp, {
197        values: Rows::Count(1),
198    });
199
200    // ========== VERIFY LOG IS EMPTY ==========
201    assert!(test.log().is_empty(), "Log should be empty");
202    Ok(())
203}