From 5b9aa3dccbe36f5e1c43b1935ab3d9b9eaa57008 Mon Sep 17 00:00:00 2001 From: Elijah Date: Fri, 6 Mar 2026 16:21:06 +0000 Subject: [PATCH 1/3] remove async trait from Model and DatabaseBackend --- cot-macros/src/model.rs | 2 +- cot/src/db.rs | 230 ++++++++++++++++++++++++++++++++++------ 2 files changed, 201 insertions(+), 31 deletions(-) diff --git a/cot-macros/src/model.rs b/cot-macros/src/model.rs index 91006c40..c7788174 100644 --- a/cot-macros/src/model.rs +++ b/cot-macros/src/model.rs @@ -176,7 +176,7 @@ impl ModelBuilder { let fields_as_get_values = &self.fields_as_get_values; quote! { - #[#crate_ident::__private::async_trait] + // #[#crate_ident::__private::async_trait] #[automatically_derived] impl #orm_ident::Model for #name { type Fields = #fields_struct_name; diff --git a/cot/src/db.rs b/cot/src/db.rs index 445dd972..f27ef955 100644 --- a/cot/src/db.rs +++ b/cot/src/db.rs @@ -17,6 +17,7 @@ mod sea_query_db; use std::fmt::{Display, Formatter, Write}; use std::hash::Hash; +use std::pin::Pin; use std::str::FromStr; use std::sync::Arc; @@ -151,7 +152,7 @@ pub type Result = std::result::Result; /// name: String, /// } /// ``` -#[async_trait] +// #[async_trait] #[diagnostic::on_unimplemented( message = "`{Self}` is not marked as a database model", label = "`{Self}` is not annotated with `#[cot::db::model]`", @@ -228,10 +229,10 @@ pub trait Model: Sized + Send + 'static { /// This method can return an error if the model instance could not be /// found in the database, or there was a problem with the database /// connection. - async fn get_by_primary_key( + fn get_by_primary_key( db: &DB, pk: Self::PrimaryKey, - ) -> Result>; + ) -> impl Future>>; /// Inserts the model instance to the database, or updates an instance /// with the same primary key if it already exists. @@ -245,9 +246,9 @@ pub trait Model: Sized + Send + 'static { /// inserted into the database, for instance because the migrations /// haven't been applied, or there was a problem with the database /// connection. - async fn save(&mut self, db: &DB) -> Result<()> { - db.insert_or_update(self).await?; - Ok(()) + fn save(&mut self, db: &DB) -> impl Future> { + async move { db.insert_or_update(self).await } + // Ok(()) } /// Insert the model instance to the database. @@ -258,9 +259,9 @@ pub trait Model: Sized + Send + 'static { /// inserted into the database, for instance because the migrations /// haven't been applied, or there was a problem with the database /// connection. - async fn insert(&mut self, db: &DB) -> Result<()> { - db.insert(self).await?; - Ok(()) + fn insert(&mut self, db: &DB) -> impl Future> { + async move { db.insert(self).await } + // Ok(()) } /// Update the model instance in the database. @@ -274,9 +275,9 @@ pub trait Model: Sized + Send + 'static { /// /// This method can return an error if the model with the given primary key /// could not be found in the database. - async fn update(&mut self, db: &DB) -> Result<()> { - db.update(self).await?; - Ok(()) + fn update(&mut self, db: &DB) -> impl Future> { + async move { db.update(self).await } + // Ok(()) } /// Bulk insert multiple model instances to the database in a single query. @@ -318,9 +319,9 @@ pub trait Model: Sized + Send + 'static { /// // After insertion, all todos have populated IDs /// assert!(todos[0].id.is_fixed()); /// ``` - async fn bulk_insert(db: &DB, instances: &mut [Self]) -> Result<()> { - db.bulk_insert(instances).await?; - Ok(()) + fn bulk_insert(db: &DB, instances: &mut [Self]) -> impl Future> { + async move{ db.bulk_insert(instances).await } + // Ok(()) } /// Bulk insert multiple model instances to the database in a single query, @@ -357,15 +358,130 @@ pub trait Model: Sized + Send + 'static { /// // After insertion, all todos have populated IDs /// assert!(todos[0].id.is_fixed()); /// ``` - async fn bulk_insert_or_update( + fn bulk_insert_or_update( db: &DB, instances: &mut [Self], - ) -> Result<()> { - db.bulk_insert_or_update(instances).await?; - Ok(()) + ) -> impl Future> { + async move{ db.bulk_insert_or_update(instances).await } + // Ok(()) } } +// pub(crate) trait BoxModel: Sized + Send + 'static { +// type Fields; +// type PrimaryKey: PrimaryKey; +// +// const APP_NAME: &'static str; +// const TABLE_NAME: Identifier; +// const PRIMARY_KEY_NAME: Identifier; +// const COLUMNS: &'static [Column]; +// +// fn from_db(db_row: Row) -> Result; +// +// fn update_from_db(&mut self, db_row: Row, columns: &[usize]) -> Result<()>; +// +// fn primary_key(&self) -> &Self::PrimaryKey; +// +// fn set_primary_key(&mut self, primary_key: Self::PrimaryKey); +// +// fn get_values(&self, columns: &[usize]) -> Vec<&dyn ToDbFieldValue>; +// +// // #[must_use] +// // fn objects() -> Query{ +// // Query::new() +// // } +// +// fn get_by_primary_key( +// db: &DB, +// pk: Self::PrimaryKey, +// ) -> std::pin::Pin>> + Send>>; +// +// +// fn insert<'a>( +// &'a mut self, +// db: &'a impl DatabaseBackend, +// ) -> std::pin::Pin> + Send + 'a>>; +// +// fn update<'a>( +// &'a mut self, +// db: &'a dyn DatabaseBackend, +// ) -> std::pin::Pin> + Send + 'a>>; +// +// fn bulk_insert<'a>( +// db: &'a dyn DatabaseBackend, +// instances: &'a mut [Self], +// ) -> std::pin::Pin> + Send + 'a>>; +// +// fn bulk_insert_or_update<'a>( +// db: &'a dyn DatabaseBackend, +// instances: &'a mut [Self], +// ) -> std::pin::Pin> + Send + 'a>>; +// } +// +// +// impl BoxModel for T { +// type Fields = T::Fields; +// type PrimaryKey = T::PrimaryKey; +// +// const APP_NAME: &'static str = T::APP_NAME; +// const TABLE_NAME: Identifier = T::TABLE_NAME; +// const PRIMARY_KEY_NAME: Identifier = T::PRIMARY_KEY_NAME; +// const COLUMNS: &'static [Column] = T::COLUMNS; +// +// fn from_db(db_row: Row) -> Result { +// T::from_db(db_row) +// } +// +// fn update_from_db(&mut self, db_row: Row, columns: &[usize]) -> Result<()> { +// T::update_from_db(self, db_row, columns) +// } +// +// fn primary_key(&self) -> &Self::PrimaryKey { +// self.primary_key() +// } +// +// fn set_primary_key(&mut self, primary_key: Self::PrimaryKey) { +// self.set_primary_key(primary_key); +// } +// +// fn get_values(&self, columns: &[usize]) -> Vec<&dyn ToDbFieldValue> { +// self.get_values(columns) +// } +// +// fn get_by_primary_key( +// db: &DB, +// pk: Self::PrimaryKey, +// ) -> std::pin::Pin>> + Send>> { +// Box::pin(async move { T::get_by_primary_key(db, pk).await }) +// } +// +// fn insert<'a>( +// &'a mut self, +// db: &'a dyn BoxDatabaseBackend, +// ) -> std::pin::Pin> + Send + 'a>> { +// Box::pin(async move { self.insert(db).await }) +// } +// +// fn update<'a>( +// &'a mut self, +// db: &'a dyn BoxDatabaseBackend, +// ) -> std::pin::Pin> + Send + 'a>> { +// Box::pin(async move { self.update(db).await }) +// } +// +// fn bulk_insert<'a>( +// db: &'a dyn BoxDatabaseBackend, +// instances: &'a mut [Self], +// ) -> std::pin::Pin> + Send + 'a>> { +// Box::pin(async move { Self::bulk_insert(db, instances).await }) +// } +// +// fn bulk_insert_or_update<'a>(db: &'a dyn BoxDatabaseBackend, instances: &'a mut [Self]) -> Pin> + Send + 'a>> { +// Box::pin(async move { Self::bulk_insert_or_update(db, instances).await }) +// } +// } + + /// An identifier structure that holds table or column name as a string. #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Display, Deref)] pub struct Identifier(&'static str); @@ -1590,7 +1706,7 @@ impl ColumnTypeMapper for Database { /// /// This trait is used to provide a backend for the database. #[cfg_attr(test, automock)] -#[async_trait] +// #[async_trait] pub trait DatabaseBackend: Send + Sync { /// Inserts a new row into the database, or updates an existing row if it /// already exists. @@ -1600,7 +1716,7 @@ pub trait DatabaseBackend: Send + Sync { /// This method can return an error if the row could not be inserted into /// the database, for instance because the migrations haven't been /// applied, or there was a problem with the database connection. - async fn insert_or_update(&self, data: &mut T) -> Result<()>; + fn insert_or_update(&self, data: &mut T) -> impl Future>; /// Inserts a new row into the database. /// @@ -1609,7 +1725,7 @@ pub trait DatabaseBackend: Send + Sync { /// This method can return an error if the row could not be inserted into /// the database, for instance because the migrations haven't been /// applied, or there was a problem with the database connection. - async fn insert(&self, data: &mut T) -> Result<()>; + fn insert(&self, data: &mut T) -> impl Future>; /// Updates an existing row in the database. /// @@ -1618,7 +1734,7 @@ pub trait DatabaseBackend: Send + Sync { /// This method can return an error if the row could not be updated in the /// database, for instance because the migrations haven't been applied, or /// there was a problem with the database connection. - async fn update(&self, data: &mut T) -> Result<()>; + fn update(&self, data: &mut T) -> impl Future>; /// Bulk inserts multiple rows into the database. /// @@ -1627,7 +1743,7 @@ pub trait DatabaseBackend: Send + Sync { /// This method can return an error if the rows could not be inserted into /// the database, for instance because the migrations haven't been /// applied, or there was a problem with the database connection. - async fn bulk_insert(&self, data: &mut [T]) -> Result<()>; + fn bulk_insert(&self, data: &mut [T]) -> impl Future>; /// Bulk inserts multiple rows into the database, or updates existing rows /// if they already exist. @@ -1637,7 +1753,7 @@ pub trait DatabaseBackend: Send + Sync { /// This method can return an error if the rows could not be inserted into /// the database, for instance because the migrations haven't been /// applied, or there was a problem with the database connection. - async fn bulk_insert_or_update(&self, data: &mut [T]) -> Result<()>; + fn bulk_insert_or_update(&self, data: &mut [T]) -> impl Future>; /// Executes a query and returns the results converted to the model type. /// @@ -1650,7 +1766,7 @@ pub trait DatabaseBackend: Send + Sync { /// generated or applied). /// /// Can return an error if the database connection is lost. - async fn query(&self, query: &Query) -> Result>; + fn query(&self, query: &Query) -> impl Future>>; /// Returns the first row that matches the given query. If no rows match the /// query, returns `None`. @@ -1664,7 +1780,7 @@ pub trait DatabaseBackend: Send + Sync { /// applied). /// /// Can return an error if the database connection is lost. - async fn get(&self, query: &Query) -> Result>; + fn get(&self, query: &Query) -> impl Future>>; /// Returns whether a row exists that matches the given query. /// @@ -1677,7 +1793,7 @@ pub trait DatabaseBackend: Send + Sync { /// applied). /// /// Can return an error if the database connection is lost. - async fn exists(&self, query: &Query) -> Result; + fn exists(&self, query: &Query) -> impl Future>; /// Deletes all rows that match the given query. /// @@ -1690,10 +1806,64 @@ pub trait DatabaseBackend: Send + Sync { /// applied). /// /// Can return an error if the database connection is lost. - async fn delete(&self, query: &Query) -> Result; + fn delete(&self, query: &Query) -> impl Future>; } -#[async_trait] + +// pub(crate) trait BoxDatabaseBackend: Send + Sync { +// fn insert_or_update<'a, T: Model>(&'a self, data: &'a mut T) -> Pin> + Send + 'a>>; +// fn insert<'a, T: Model>(&'a self, data: &'a mut T) -> Pin> + Send + 'a>>; +// fn update<'a, T: Model>(&'a self, data: &'a mut T) -> Pin> + Send + 'a>>; +// fn bulk_insert<'a, T: Model>(&'a self, data: &'a mut [T]) -> Pin> + Send + 'a>>; +// fn bulk_insert_or_update<'a, T: Model>(&'a self, data: &'a mut [T]) -> Pin> + Send + 'a>>; +// fn query<'a, T: Model>(&'a self, query: &'a Query) -> Pin>> + Send + 'a>>; +// fn get<'a, T: Model>(&'a self, query: &'a Query) -> Pin>> + Send + 'a>>; +// fn exists<'a, T: Model>(&'a self, query: &'a Query) -> Pin> + Send + 'a>>; +// fn delete<'a, T: Model>(&'a self, query: &'a Query) -> Pin> + Send + 'a>>; +// } +// +// +// +// impl BoxDatabaseBackend for T { +// fn insert_or_update<'a, M: Model>(&'a self, data: &'a mut M) -> Pin> + Send + 'a>> { +// Box::pin(self.insert_or_update(data)) +// } +// +// fn insert<'a, M: Model>(&'a self, data: &'a mut M) -> Pin> + Send + 'a>> { +// Box::pin(self.insert(data)) +// } +// +// fn update<'a, M: Model>(&'a self, data: &'a mut M) -> Pin> + Send + 'a>> { +// Box::pin(self.update(data)) +// } +// +// fn bulk_insert<'a, M: Model>(&'a self, data: &'a mut [M]) -> Pin> + Send + 'a>> { +// Box::pin(self.bulk_insert(data)) +// } +// +// fn bulk_insert_or_update<'a, M: Model>(&'a self, data: &'a mut [M]) -> Pin> + Send + 'a>> { +// Box::pin(self.bulk_insert_or_update(data)) +// } +// +// fn query<'a, M: Model>(&'a self, query: &'a Query) -> Pin>> + Send + 'a>> { +// Box::pin(self.query(query)) +// } +// +// fn get<'a, M: Model>(&'a self, query: &'a Query) -> Pin>> + Send + 'a>> { +// Box::pin(self.get(query)) +// } +// +// fn exists<'a, M: Model>(&'a self, query: &'a Query) -> Pin> + Send + 'a>> { +// Box::pin(self.exists(query)) +// } +// +// fn delete<'a, M: Model>(&'a self, query: &'a Query) -> Pin> + Send + 'a>> { +// Box::pin(self.delete(query)) +// } +// } + + +// #[async_trait] impl DatabaseBackend for Database { async fn insert_or_update(&self, data: &mut T) -> Result<()> { Database::insert_or_update(self, data).await From f055f99e8cfe969482fa2a9ee5569fe27b65d28f Mon Sep 17 00:00:00 2001 From: Elijah Date: Wed, 18 Mar 2026 21:35:14 +0000 Subject: [PATCH 2/3] fix tests --- cot/src/auth/db.rs | 25 ++--- cot/src/db.rs | 216 ++++---------------------------------------- cot/src/db/query.rs | 13 ++- cot/src/lib.rs | 3 +- 4 files changed, 43 insertions(+), 214 deletions(-) diff --git a/cot/src/auth/db.rs b/cot/src/auth/db.rs index 8eb6190f..0a3083f5 100644 --- a/cot/src/auth/db.rs +++ b/cot/src/auth/db.rs @@ -615,7 +615,7 @@ mod tests { let mut mock_db = MockDatabaseBackend::new(); mock_db .expect_insert::() - .returning(|_| Ok(())); + .returning(|_| Box::pin(async { Ok(()) })); let username = "testuser".to_string(); let password = Password::new("password123"); @@ -636,9 +636,10 @@ mod tests { &Password::new("password123"), ); - mock_db - .expect_get::() - .returning(move |_| Ok(Some(user.clone()))); + mock_db.expect_get::().returning(move |_| { + let user = user.clone(); + Box::pin(async move { Ok(Some(user.clone())) }) + }); let result = DatabaseUser::get_by_id(&mock_db, 1).await.unwrap(); assert!(result.is_some()); @@ -655,9 +656,10 @@ mod tests { &Password::new("password123"), ); - mock_db - .expect_get::() - .returning(move |_| Ok(Some(user.clone()))); + mock_db.expect_get::().returning(move |_| { + let user = user.clone(); + Box::pin(async move { Ok(Some(user.clone())) }) + }); let credentials = DatabaseUserCredentials::new("testuser".to_string(), Password::new("password123")); @@ -675,7 +677,7 @@ mod tests { mock_db .expect_get::() - .returning(move |_| Ok(None)); + .returning(|_| Box::pin(async { Ok(None) })); let credentials = DatabaseUserCredentials::new("testuser".to_string(), Password::new("password123")); @@ -695,9 +697,10 @@ mod tests { &Password::new("password123"), ); - mock_db - .expect_get::() - .returning(move |_| Ok(Some(user.clone()))); + mock_db.expect_get::().returning(move |_| { + let user = user.clone(); + Box::pin(async move { Ok(Some(user.clone())) }) + }); let credentials = DatabaseUserCredentials::new("testuser".to_string(), Password::new("invalid")); diff --git a/cot/src/db.rs b/cot/src/db.rs index f27ef955..6d18af8d 100644 --- a/cot/src/db.rs +++ b/cot/src/db.rs @@ -17,11 +17,9 @@ mod sea_query_db; use std::fmt::{Display, Formatter, Write}; use std::hash::Hash; -use std::pin::Pin; use std::str::FromStr; use std::sync::Arc; -use async_trait::async_trait; use cot_core::error::impl_into_cot_error; pub use cot_macros::{model, query}; use derive_more::{Debug, Deref, Display}; @@ -152,7 +150,6 @@ pub type Result = std::result::Result; /// name: String, /// } /// ``` -// #[async_trait] #[diagnostic::on_unimplemented( message = "`{Self}` is not marked as a database model", label = "`{Self}` is not annotated with `#[cot::db::model]`", @@ -232,7 +229,7 @@ pub trait Model: Sized + Send + 'static { fn get_by_primary_key( db: &DB, pk: Self::PrimaryKey, - ) -> impl Future>>; + ) -> impl Future>>; /// Inserts the model instance to the database, or updates an instance /// with the same primary key if it already exists. @@ -246,9 +243,8 @@ pub trait Model: Sized + Send + 'static { /// inserted into the database, for instance because the migrations /// haven't been applied, or there was a problem with the database /// connection. - fn save(&mut self, db: &DB) -> impl Future> { + fn save(&mut self, db: &DB) -> impl Future> { async move { db.insert_or_update(self).await } - // Ok(()) } /// Insert the model instance to the database. @@ -259,9 +255,8 @@ pub trait Model: Sized + Send + 'static { /// inserted into the database, for instance because the migrations /// haven't been applied, or there was a problem with the database /// connection. - fn insert(&mut self, db: &DB) -> impl Future> { + fn insert(&mut self, db: &DB) -> impl Future> { async move { db.insert(self).await } - // Ok(()) } /// Update the model instance in the database. @@ -275,9 +270,8 @@ pub trait Model: Sized + Send + 'static { /// /// This method can return an error if the model with the given primary key /// could not be found in the database. - fn update(&mut self, db: &DB) -> impl Future> { + fn update(&mut self, db: &DB) -> impl Future> { async move { db.update(self).await } - // Ok(()) } /// Bulk insert multiple model instances to the database in a single query. @@ -319,9 +313,11 @@ pub trait Model: Sized + Send + 'static { /// // After insertion, all todos have populated IDs /// assert!(todos[0].id.is_fixed()); /// ``` - fn bulk_insert(db: &DB, instances: &mut [Self]) -> impl Future> { - async move{ db.bulk_insert(instances).await } - // Ok(()) + fn bulk_insert( + db: &DB, + instances: &mut [Self], + ) -> impl Future> { + async move { db.bulk_insert(instances).await } } /// Bulk insert multiple model instances to the database in a single query, @@ -361,127 +357,11 @@ pub trait Model: Sized + Send + 'static { fn bulk_insert_or_update( db: &DB, instances: &mut [Self], - ) -> impl Future> { - async move{ db.bulk_insert_or_update(instances).await } - // Ok(()) + ) -> impl Future> { + async move { db.bulk_insert_or_update(instances).await } } } -// pub(crate) trait BoxModel: Sized + Send + 'static { -// type Fields; -// type PrimaryKey: PrimaryKey; -// -// const APP_NAME: &'static str; -// const TABLE_NAME: Identifier; -// const PRIMARY_KEY_NAME: Identifier; -// const COLUMNS: &'static [Column]; -// -// fn from_db(db_row: Row) -> Result; -// -// fn update_from_db(&mut self, db_row: Row, columns: &[usize]) -> Result<()>; -// -// fn primary_key(&self) -> &Self::PrimaryKey; -// -// fn set_primary_key(&mut self, primary_key: Self::PrimaryKey); -// -// fn get_values(&self, columns: &[usize]) -> Vec<&dyn ToDbFieldValue>; -// -// // #[must_use] -// // fn objects() -> Query{ -// // Query::new() -// // } -// -// fn get_by_primary_key( -// db: &DB, -// pk: Self::PrimaryKey, -// ) -> std::pin::Pin>> + Send>>; -// -// -// fn insert<'a>( -// &'a mut self, -// db: &'a impl DatabaseBackend, -// ) -> std::pin::Pin> + Send + 'a>>; -// -// fn update<'a>( -// &'a mut self, -// db: &'a dyn DatabaseBackend, -// ) -> std::pin::Pin> + Send + 'a>>; -// -// fn bulk_insert<'a>( -// db: &'a dyn DatabaseBackend, -// instances: &'a mut [Self], -// ) -> std::pin::Pin> + Send + 'a>>; -// -// fn bulk_insert_or_update<'a>( -// db: &'a dyn DatabaseBackend, -// instances: &'a mut [Self], -// ) -> std::pin::Pin> + Send + 'a>>; -// } -// -// -// impl BoxModel for T { -// type Fields = T::Fields; -// type PrimaryKey = T::PrimaryKey; -// -// const APP_NAME: &'static str = T::APP_NAME; -// const TABLE_NAME: Identifier = T::TABLE_NAME; -// const PRIMARY_KEY_NAME: Identifier = T::PRIMARY_KEY_NAME; -// const COLUMNS: &'static [Column] = T::COLUMNS; -// -// fn from_db(db_row: Row) -> Result { -// T::from_db(db_row) -// } -// -// fn update_from_db(&mut self, db_row: Row, columns: &[usize]) -> Result<()> { -// T::update_from_db(self, db_row, columns) -// } -// -// fn primary_key(&self) -> &Self::PrimaryKey { -// self.primary_key() -// } -// -// fn set_primary_key(&mut self, primary_key: Self::PrimaryKey) { -// self.set_primary_key(primary_key); -// } -// -// fn get_values(&self, columns: &[usize]) -> Vec<&dyn ToDbFieldValue> { -// self.get_values(columns) -// } -// -// fn get_by_primary_key( -// db: &DB, -// pk: Self::PrimaryKey, -// ) -> std::pin::Pin>> + Send>> { -// Box::pin(async move { T::get_by_primary_key(db, pk).await }) -// } -// -// fn insert<'a>( -// &'a mut self, -// db: &'a dyn BoxDatabaseBackend, -// ) -> std::pin::Pin> + Send + 'a>> { -// Box::pin(async move { self.insert(db).await }) -// } -// -// fn update<'a>( -// &'a mut self, -// db: &'a dyn BoxDatabaseBackend, -// ) -> std::pin::Pin> + Send + 'a>> { -// Box::pin(async move { self.update(db).await }) -// } -// -// fn bulk_insert<'a>( -// db: &'a dyn BoxDatabaseBackend, -// instances: &'a mut [Self], -// ) -> std::pin::Pin> + Send + 'a>> { -// Box::pin(async move { Self::bulk_insert(db, instances).await }) -// } -// -// fn bulk_insert_or_update<'a>(db: &'a dyn BoxDatabaseBackend, instances: &'a mut [Self]) -> Pin> + Send + 'a>> { -// Box::pin(async move { Self::bulk_insert_or_update(db, instances).await }) -// } -// } - - /// An identifier structure that holds table or column name as a string. #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Display, Deref)] pub struct Identifier(&'static str); @@ -1706,7 +1586,6 @@ impl ColumnTypeMapper for Database { /// /// This trait is used to provide a backend for the database. #[cfg_attr(test, automock)] -// #[async_trait] pub trait DatabaseBackend: Send + Sync { /// Inserts a new row into the database, or updates an existing row if it /// already exists. @@ -1716,7 +1595,7 @@ pub trait DatabaseBackend: Send + Sync { /// This method can return an error if the row could not be inserted into /// the database, for instance because the migrations haven't been /// applied, or there was a problem with the database connection. - fn insert_or_update(&self, data: &mut T) -> impl Future>; + fn insert_or_update(&self, data: &mut T) -> impl Future>; /// Inserts a new row into the database. /// @@ -1725,7 +1604,7 @@ pub trait DatabaseBackend: Send + Sync { /// This method can return an error if the row could not be inserted into /// the database, for instance because the migrations haven't been /// applied, or there was a problem with the database connection. - fn insert(&self, data: &mut T) -> impl Future>; + fn insert(&self, data: &mut T) -> impl Future>; /// Updates an existing row in the database. /// @@ -1734,7 +1613,7 @@ pub trait DatabaseBackend: Send + Sync { /// This method can return an error if the row could not be updated in the /// database, for instance because the migrations haven't been applied, or /// there was a problem with the database connection. - fn update(&self, data: &mut T) -> impl Future>; + fn update(&self, data: &mut T) -> impl Future>; /// Bulk inserts multiple rows into the database. /// @@ -1743,7 +1622,7 @@ pub trait DatabaseBackend: Send + Sync { /// This method can return an error if the rows could not be inserted into /// the database, for instance because the migrations haven't been /// applied, or there was a problem with the database connection. - fn bulk_insert(&self, data: &mut [T]) -> impl Future>; + fn bulk_insert(&self, data: &mut [T]) -> impl Future>; /// Bulk inserts multiple rows into the database, or updates existing rows /// if they already exist. @@ -1753,7 +1632,7 @@ pub trait DatabaseBackend: Send + Sync { /// This method can return an error if the rows could not be inserted into /// the database, for instance because the migrations haven't been /// applied, or there was a problem with the database connection. - fn bulk_insert_or_update(&self, data: &mut [T]) -> impl Future>; + fn bulk_insert_or_update(&self, data: &mut [T]) -> impl Future>; /// Executes a query and returns the results converted to the model type. /// @@ -1766,7 +1645,7 @@ pub trait DatabaseBackend: Send + Sync { /// generated or applied). /// /// Can return an error if the database connection is lost. - fn query(&self, query: &Query) -> impl Future>>; + fn query(&self, query: &Query) -> impl Future>>; /// Returns the first row that matches the given query. If no rows match the /// query, returns `None`. @@ -1780,7 +1659,7 @@ pub trait DatabaseBackend: Send + Sync { /// applied). /// /// Can return an error if the database connection is lost. - fn get(&self, query: &Query) -> impl Future>>; + fn get(&self, query: &Query) -> impl Future>>; /// Returns whether a row exists that matches the given query. /// @@ -1793,7 +1672,7 @@ pub trait DatabaseBackend: Send + Sync { /// applied). /// /// Can return an error if the database connection is lost. - fn exists(&self, query: &Query) -> impl Future>; + fn exists(&self, query: &Query) -> impl Future>; /// Deletes all rows that match the given query. /// @@ -1806,64 +1685,9 @@ pub trait DatabaseBackend: Send + Sync { /// applied). /// /// Can return an error if the database connection is lost. - fn delete(&self, query: &Query) -> impl Future>; + fn delete(&self, query: &Query) -> impl Future>; } - -// pub(crate) trait BoxDatabaseBackend: Send + Sync { -// fn insert_or_update<'a, T: Model>(&'a self, data: &'a mut T) -> Pin> + Send + 'a>>; -// fn insert<'a, T: Model>(&'a self, data: &'a mut T) -> Pin> + Send + 'a>>; -// fn update<'a, T: Model>(&'a self, data: &'a mut T) -> Pin> + Send + 'a>>; -// fn bulk_insert<'a, T: Model>(&'a self, data: &'a mut [T]) -> Pin> + Send + 'a>>; -// fn bulk_insert_or_update<'a, T: Model>(&'a self, data: &'a mut [T]) -> Pin> + Send + 'a>>; -// fn query<'a, T: Model>(&'a self, query: &'a Query) -> Pin>> + Send + 'a>>; -// fn get<'a, T: Model>(&'a self, query: &'a Query) -> Pin>> + Send + 'a>>; -// fn exists<'a, T: Model>(&'a self, query: &'a Query) -> Pin> + Send + 'a>>; -// fn delete<'a, T: Model>(&'a self, query: &'a Query) -> Pin> + Send + 'a>>; -// } -// -// -// -// impl BoxDatabaseBackend for T { -// fn insert_or_update<'a, M: Model>(&'a self, data: &'a mut M) -> Pin> + Send + 'a>> { -// Box::pin(self.insert_or_update(data)) -// } -// -// fn insert<'a, M: Model>(&'a self, data: &'a mut M) -> Pin> + Send + 'a>> { -// Box::pin(self.insert(data)) -// } -// -// fn update<'a, M: Model>(&'a self, data: &'a mut M) -> Pin> + Send + 'a>> { -// Box::pin(self.update(data)) -// } -// -// fn bulk_insert<'a, M: Model>(&'a self, data: &'a mut [M]) -> Pin> + Send + 'a>> { -// Box::pin(self.bulk_insert(data)) -// } -// -// fn bulk_insert_or_update<'a, M: Model>(&'a self, data: &'a mut [M]) -> Pin> + Send + 'a>> { -// Box::pin(self.bulk_insert_or_update(data)) -// } -// -// fn query<'a, M: Model>(&'a self, query: &'a Query) -> Pin>> + Send + 'a>> { -// Box::pin(self.query(query)) -// } -// -// fn get<'a, M: Model>(&'a self, query: &'a Query) -> Pin>> + Send + 'a>> { -// Box::pin(self.get(query)) -// } -// -// fn exists<'a, M: Model>(&'a self, query: &'a Query) -> Pin> + Send + 'a>> { -// Box::pin(self.exists(query)) -// } -// -// fn delete<'a, M: Model>(&'a self, query: &'a Query) -> Pin> + Send + 'a>> { -// Box::pin(self.delete(query)) -// } -// } - - -// #[async_trait] impl DatabaseBackend for Database { async fn insert_or_update(&self, data: &mut T) -> Result<()> { Database::insert_or_update(self, data).await diff --git a/cot/src/db/query.rs b/cot/src/db/query.rs index 139a7ca7..1ae5c239 100644 --- a/cot/src/db/query.rs +++ b/cot/src/db/query.rs @@ -1481,7 +1481,8 @@ mod tests { #[cot::test] async fn query_all() { let mut db = MockDatabaseBackend::new(); - db.expect_query().returning(|_| Ok(Vec::::new())); + db.expect_query() + .returning(|_| Box::pin(async { Ok(Vec::::new()) })); let query: Query = Query::new(); let result = query.all(&db).await; @@ -1492,7 +1493,8 @@ mod tests { #[cot::test] async fn query_get() { let mut db = MockDatabaseBackend::new(); - db.expect_get().returning(|_| Ok(Option::::None)); + db.expect_get() + .returning(|_| Box::pin(async { Ok(Option::::None) })); let query: Query = Query::new(); let result = query.get(&db).await; @@ -1504,7 +1506,7 @@ mod tests { async fn query_exists() { let mut db = MockDatabaseBackend::new(); db.expect_exists() - .returning(|_: &Query| Ok(false)); + .returning(|_: &Query| Box::pin(async { Ok(false) })); let query: Query = Query::new(); @@ -1515,8 +1517,9 @@ mod tests { #[cot::test] async fn query_delete() { let mut db = MockDatabaseBackend::new(); - db.expect_delete() - .returning(|_: &Query| Ok(StatementResult::new(RowsNum(0)))); + db.expect_delete().returning(|_: &Query| { + Box::pin(async { Ok(StatementResult::new(RowsNum(0))) }) + }); let query: Query = Query::new(); let result = query.delete(&db).await; diff --git a/cot/src/lib.rs b/cot/src/lib.rs index 22ea64d5..cc11ba1a 100644 --- a/cot/src/lib.rs +++ b/cot/src/lib.rs @@ -84,7 +84,6 @@ pub(crate) mod utils; #[cfg(feature = "openapi")] pub use aide; -pub use bytes; /// A wrapper around a handler that's used in [`Bootstrapper`]. /// /// It is returned by [`Bootstrapper::finish`]. Typically, you don't need to @@ -182,9 +181,9 @@ pub use cot_macros::e2e_test; /// ``` pub use cot_macros::main; pub use cot_macros::test; -pub use http; #[cfg(feature = "openapi")] pub use schemars; +pub use {bytes, http}; pub use crate::__private::askama::{Template, filter_fn}; pub use crate::project::{ From ea9b6c224c0f49711c4fbab3319c481596757742 Mon Sep 17 00:00:00 2001 From: Elijah Date: Wed, 18 Mar 2026 21:41:34 +0000 Subject: [PATCH 3/3] remove dead code --- cot-macros/src/model.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/cot-macros/src/model.rs b/cot-macros/src/model.rs index c7788174..28135814 100644 --- a/cot-macros/src/model.rs +++ b/cot-macros/src/model.rs @@ -160,7 +160,6 @@ impl ModelBuilder { #[must_use] fn build_model_impl(&self) -> TokenStream { - let crate_ident = cot_ident(); let orm_ident = orm_ident(); let name = &self.name; @@ -176,7 +175,6 @@ impl ModelBuilder { let fields_as_get_values = &self.fields_as_get_values; quote! { - // #[#crate_ident::__private::async_trait] #[automatically_derived] impl #orm_ident::Model for #name { type Fields = #fields_struct_name;