sql_query 0.0.0

composible sql query builder, with support of binding into query buffer
Documentation
use futures_util::Future;
use sqlx::{database::HasArguments, Database};

use crate::{
    create_table_st::CreateTableSt, delete_st::DeleteSt,
    executable::InnerExecutable, insert_many_st::InsertMany,
    insert_one_st::InsertStOne, returning::ReturningClause,
    select_st::SelectSt, update_st::UpdateSt, HasQuery, Query,
    SupportNamedBind,
};

pub trait ExecuteNoCache<'q, S: Database>:
    NoCache<'q, S> + Sized
{
    fn execute<E>(
        self,
        executor: E,
    ) -> impl Future<Output = Result<S::QueryResult, sqlx::Error>>
           + Send
    where
        E: for<'e> sqlx::Executor<'e, Database = S>,
    {
        let (query, args) = self.build();
        async move {
            InnerExecutable {
                stmt: query.as_str(),
                buffer: args,
                persistent: false,
            }
            .execute(executor)
            .await
        }
    }
    fn fetch_one<E, O, F>(
        self,
        executor: E,
        with: F,
    ) -> impl Future<Output = Result<O, sqlx::Error>> + Send
    where
        E: for<'e> sqlx::Executor<'e, Database = S>,
        F: FnOnce(S::Row) -> Result<O, sqlx::Error> + Send,
    {
        let (query, args) = self.build();
        async move {
            InnerExecutable {
                stmt: query.as_str(),
                buffer: args,
                persistent: false,
            }
            .fetch_one_with(executor, with)
            .await
        }
    }
    fn fetch_optional<E, O, F>(
        self,
        executor: E,
        with: F,
    ) -> impl Future<Output = Result<Option<O>, sqlx::Error>> + Send
    where
        E: for<'e> sqlx::Executor<'e, Database = S>,
        F: FnOnce(S::Row) -> Result<O, sqlx::Error> + Send,
    {
        let (query, args) = self.build();
        async move {
            InnerExecutable {
                stmt: query.as_str(),
                buffer: args,
                persistent: false,
            }
            .fetch_optional_with(executor, with)
            .await
        }
    }
    fn fetch_all<E, O, F>(
        self,
        executor: E,
        with: F,
    ) -> impl Future<Output = Result<Vec<O>, sqlx::Error>> + Send
    where
        E: for<'e> sqlx::Executor<'e, Database = S>,
        F: FnMut(S::Row) -> Result<O, sqlx::Error> + Send,
    {
        let (query, args) = self.build();
        async move {
            InnerExecutable {
                stmt: query.as_str(),
                buffer: args,
                persistent: false,
            }
            .fetch_all_with(executor, with)
            .await
        }
    }
}

impl<'q, S, T> ExecuteNoCache<'q, S> for T
where
    S: Database,
    T: NoCache<'q, S>,
{
}

pub trait NoCache<'q, S: Database> {
    fn build(
        self,
    ) -> (String, <S as HasArguments<'q>>::Arguments);
}

impl<'q, S, Q> NoCache<'q, S> for CreateTableSt<'q, S, Q>
where
    S: Database + SupportNamedBind,
    Q: Query<S, Output = <S as HasArguments<'q>>::Arguments>,
{
    fn build(
        self,
    ) -> (String, <S as HasArguments<'q>>::Arguments) {
        <Self as HasQuery<S, Q>>::_build(self)
    }
}

impl<'q, S, Q> NoCache<'q, S> for SelectSt<S, Q>
where
    Q: Query<S, Output = <S as HasArguments<'q>>::Arguments>,
    S: Database + SupportNamedBind,
{
    fn build(
        self,
    ) -> (String, <S as HasArguments<'q>>::Arguments) {
        self._build()
    }
}

impl<'q, S, Q, R> NoCache<'q, S> for DeleteSt<S, Q, R>
where
    R: ReturningClause,
    S: Database + SupportNamedBind,
    Q: Query<S, Output = <S as HasArguments<'q>>::Arguments>,
{
    fn build(
        self,
    ) -> (String, <S as HasArguments<'q>>::Arguments) {
        self._build()
    }
}
impl<'q, S, R, Q> NoCache<'q, S> for UpdateSt<S, Q, R>
where
    R: ReturningClause,
    S: Database + SupportNamedBind,
    Q: Query<S, Output = <S as HasArguments<'q>>::Arguments>,
{
    fn build(
        self,
    ) -> (String, <S as HasArguments<'q>>::Arguments) {
        self._build()
    }
}

impl<'q, S: Database, R> NoCache<'q, S>
    for InsertMany<S, <S as HasArguments<'q>>::Arguments, R>
where
    R: ReturningClause,
    S: Database + SupportNamedBind,
{
    fn build(
        self,
    ) -> (String, <S as HasArguments<'q>>::Arguments) {
        self._build()
    }
}

impl<'q, S, R> NoCache<'q, S> for InsertStOne<'q, S, R>
where
    R: ReturningClause,
    S: Database + SupportNamedBind,
{
    fn build(
        self,
    ) -> (String, <S as HasArguments<'q>>::Arguments) {
        self._build()
    }
}