co-orm 0.3.15

Implement Create, Read, Update, and Delete (CRUD) methods for sqlx.
Documentation
mod pool;

fn main() {}

#[cfg(test)]
mod test_orm {
    #![allow(unused)]
    use crate::pool::get_pool;
    use co_orm::{args, query, query_as, Crud};
    use sqlx::{types::chrono::NaiveDateTime, Execute, FromRow};

    // sqlx::FromRow
    #[derive(Debug, Clone, co_orm::FromRow)]
    struct User {
        pub id: i64,
        pub name: String,
        pub password: String,
        // #[sqlx(default)]
        pub status: Option<i32>,
    }

    // impl<'r> FromRow<'r, sqlx::mssql::MssqlRow> for User {
    //     fn from_row(row: &'r sqlx::mssql::MssqlRow) -> sqlx::Result<Self> {
    //         todo!()
    //     }
    // }

    impl User {
        #[cfg(feature = "mysql")]
        pub async fn get_by(
            pool: &sqlx::MySqlPool, where_sql: impl AsRef<str>, args: sqlx::mysql::MySqlArguments,
        ) -> sqlx::Result<Self> {
            let sql = format!(
                "SELECT {} FROM {} {}",
                "`id`,`name`,`password`",
                "users",
                where_sql.as_ref()
            );
            sqlx::query_as_with::<_, Self, _>(&sql, args).fetch_one(pool).await
        }
        #[cfg(feature = "postgres")]
        pub async fn get_by(
            pool: &sqlx::PgPool, where_sql: impl AsRef<str>, args: sqlx::postgres::PgArguments,
        ) -> sqlx::Result<Self> {
            let sql = format!(
                "SELECT {} FROM {} {}",
                "`id`,`name`,`password`",
                "users",
                where_sql.as_ref()
            );

            sqlx::query_as_with::<_, Self, _>(&sql, args).fetch_one(pool).await
        }

        #[cfg(feature = "postgres")]
        pub async fn query_page_by(
            pool: &sqlx::PgPool, where_sql: impl AsRef<str>, args: sqlx::postgres::PgArguments,
            page: i32, page_size: i32,
        ) -> sqlx::Result<(i64, Vec<Self>)> {
            use std::any::type_name_of_val;

            use sqlx::Execute;
            let sql = format!(
                "SELECT {} FROM {} {}",
                "`id`,`name`,`password`",
                "users",
                where_sql.as_ref()
            );

            // let total = sqlx::query_scalar_with::<_, i64, _>(&format!("select count(*) from ({}) as c", sql), args.0)
            //     .fetch_one(pool)
            //     .await?;
            let count_sql = format!("select count(*) from ({}) as c", sql);
            let mut a = sqlx::query_scalar_with::<_, i64, _>(&count_sql, args);
            let arg1;
            let arg2 = a.take_arguments().unwrap_or_default();
            if type_name_of_val(&arg2).contains("option") {
                arg1 = arg2.unwrap_or_default();
            } else {
            }
            let total = a.fetch_one(pool).await?;

            let sql = format!("{} LIMIT {} OFFSET {}", sql, page_size, page_size * (page - 1));
            sqlx::query_as_with::<_, Self, _>(&sql, arg1)
                .fetch_all(pool)
                .await
                .map(|list| (total, list))
        }

        #[cfg(feature = "mysql")]
        pub async fn query_page_by(
            pool: &sqlx::MySqlPool, where_sql: impl AsRef<str>, args: sqlx::mysql::MySqlArguments,
            page: i32, page_size: i32,
        ) -> sqlx::Result<(i64, Vec<Self>)> {
            use sqlx::Execute;
            let sql = format!("SELECT {} FROM {} {}", "*", "users", where_sql.as_ref());

            // let total = sqlx::query_scalar_with::<_, i64, _>(&format!("select count(*) from ({}) as c", sql), args.0)
            //     .fetch_one(pool)
            //     .await?;
            let count_sql = format!("select count(*) from ({}) as c", sql);
            let mut a = sqlx::query_scalar_with::<_, i64, _>(&count_sql, args);
            let arg1 = a.take_arguments().unwrap_or_default().unwrap_or_default();
            let total = a.fetch_one(pool).await?;

            let sql = format!("{} LIMIT {} OFFSET {}", sql, page_size, page_size * (page - 1));
            sqlx::query_as_with::<_, Self, _>(&sql, arg1)
                .fetch_all(pool)
                .await
                .map(|list| (total, list))
        }

        #[cfg(feature = "sqlite")]
        pub async fn get_by(
            pool: &sqlx::SqlitePool, where_sql: impl AsRef<str>,
            args: sqlx::sqlite::SqliteArguments<'_>,
        ) -> sqlx::Result<Self> {
            let sql = format!(
                "SELECT {} FROM {} {}",
                "`id`,`name`,`password`",
                "users",
                where_sql.as_ref()
            );

            sqlx::query_as_with::<_, Self, _>(&sql, args).fetch_one(pool).await
        }
    }

    #[cfg(feature = "mysql")]
    pub async fn update_by(
        pool: &sqlx::MySqlPool, where_sql: impl AsRef<str>, args: sqlx::mysql::MySqlArguments,
    ) -> sqlx::Result<sqlx::mysql::MySqlQueryResult> {
        use sqlx::Arguments;
        let sql = format!("UPDATE users SET status=? {}", where_sql.as_ref());
        // 期望值是update status = 0 where id = 3, 但是实际是update status = 3 where id = 0

        let mut args1: sqlx::mysql::MySqlArguments =
            sqlx::query::<sqlx::MySql>(&sql).bind(0).take_arguments().unwrap().unwrap();
        // args1.add(3);
        // 这里需要把args1和args合并, 例如 args1.add(3); 如何把args合并到args1中
        // args1.add(args);
        sqlx::query_with(&sql, args1).execute(pool).await
    }

    #[cfg(feature = "mysql")]
    #[tokio::test]
    async fn test_update_by() {
        let pool = get_pool().await.unwrap();
        let result = update_by(&pool, "where id = ?", args!(3)).await.unwrap();
        println!("{:?}", result);
    }
}