Macro postgres_query

Source
macro_rules! postgres_query {
    ($($body:tt)+) => { ... };
}
Expand description

Generate database access layer method on given struct.

This helper macro avoid boilerplate when implement database access layer. For complex sql operation, one should implement it manually.

// Example usage
#[derive(sqlx::FromRow)]
struct Account {
    id: i64,
    name: String,
    surname: String,
    active: bool,
}

// Prepared statement arguments
struct FindAccount {
    id: i64,
    active: bool,
}

impl FindAccount {
    const FETCH_SQL: &'static str = "select * from accounts where id = ?, and active = ?";

   // Use case 1, Get one record from query result.
   // -- source --
   postgres_query! {
       fetch_one(FindAccount::FETCH_SQL) -> Account,
       pub async fn get {
           id,
       }
   }
   // -- expanded --
   pub async fn get<'c, E>(&self, executor: E) -> sqlx::Result<Account>
   where
       E: sqlx::Executor<'c, Database = sqlx::Postgres>,
   {
       sqlx::query_as(FindAccount::FETCH_SQL)
           .bind(&self.id)
           .fetch_one(executor)
           .await
   }


    // Use case 2, Find one record from query result.
    // -- source --
    postgres_query! {
        fetch_optional(FindAccount::FETCH_SQL) -> Account,
        pub async fn find {
            id,
            active,
        }
    }
    // -- expanded --
    pub async fn find<'c, E>(
        &self,
        executor: E,
    ) -> sqlx::Result<Option<Account>>
    where
        E: sqlx::Executor<'c, Database = sqlx::Postgres>,
    {
        sqlx::query_as(FindAccount::FETCH_SQL)
            .bind(&self.id)
            .bind(&self.active)
            .fetch_optional(executor)
            .await
    }


    // Use case 3, Get all records from query result.
    // -- source --
    postgres_query! {
        fetch_all(FindAccount::FETCH_SQL) -> Account,
        pub async fn list {
            id,
            active,
        }
    }
    // -- expanded --
    pub async fn list<'c, E>(
        &self,
        executor: E,
    ) -> sqlx::Result<Vec<Account>>
    where
        E: sqlx::Executor<'c, Database = sqlx::Postgres>,
    {
        sqlx::query_as(FindAccount::FETCH_SQL)
            .bind(&self.id)
            .bind(&self.active)
            .fetch_all(executor)
            .await
    }
}