artis 0.2.13

Artis is a SQL library
Documentation
use std::{fmt::Debug, future::Future, sync::Arc};

use serde::de::DeserializeOwned;

use crate::{
    decode::{decode, decode_pluck},
    types::{Args, IntoChunk},
    BoxFuture, ExecResult, IntoArtis, IntoRaw, RawType, Result, Value,
};

pub trait ArtisTxExecutor: Debug + Send + Sync {
    fn query(&self, raw: String, args: Args) -> BoxFuture<'_, Result<Value>>;
    fn exec(&self, raw: String, args: Args) -> BoxFuture<'_, Result<ExecResult>>;

    fn commit(&self) -> BoxFuture<'_, Result<()>>;
    fn rollback(&self) -> BoxFuture<'_, Result<()>>;
}

#[derive(Debug)]
pub struct ArtisTx {
    c: Arc<Box<dyn ArtisTxExecutor>>,
}

impl From<Box<dyn ArtisTxExecutor>> for ArtisTx {
    fn from(value: Box<dyn ArtisTxExecutor>) -> Self {
        Self { c: Arc::new(value) }
    }
}

impl ArtisTx {
    pub async fn chunk<T, R>(&self, func: T) -> Result<R>
    where
        T: Future<Output = Result<R>>,
    {
        match func.await {
            Ok(r) => {
                self.c.commit().await?;
                Ok(r)
            }
            Err(e) => {
                self.c.rollback().await?;
                Err(e)
            }
        }
    }
}

impl IntoChunk for ArtisTx {
    async fn chunk<F, T, R>(&self, _: F) -> Result<R>
    where
        F: FnOnce(Arc<ArtisTx>) -> T,
        T: Future<Output = Result<R>>,
    {
        Err("Not support".into())
    }
}

impl IntoArtis for ArtisTx {
    async fn fetch<T: DeserializeOwned>(&self, i: &dyn IntoRaw) -> Result<T> {
        let (raw, args) = i.into_raw(RawType::Fetch);
        Ok(decode(self.c.query(raw, args).await?)?)
    }

    async fn pluck<T: DeserializeOwned>(&self, i: &dyn IntoRaw, colume: &'static str) -> Result<T> {
        let (raw, args) = i.into_raw(RawType::Fetch);
        Ok(decode_pluck(self.c.query(raw, args).await?, colume)?)
    }

    async fn saving(&self, i: &dyn IntoRaw) -> Result<Value> {
        let (raw, args) = i.into_raw(RawType::Saving);
        Ok(self.c.exec(raw, args).await?.last_insert_id)
    }

    async fn update(&self, i: &dyn IntoRaw) -> Result<u64> {
        let (raw, args) = i.into_raw(RawType::Update);
        Ok(self.c.exec(raw, args).await?.rows_affected)
    }

    async fn delete(&self, i: &dyn IntoRaw) -> Result<u64> {
        let (raw, args) = i.into_raw(RawType::Delete);
        Ok(self.c.exec(raw, args).await?.rows_affected)
    }

    async fn query(&self, i: &dyn IntoRaw) -> Result<Value> {
        let (raw, args) = i.into_raw(RawType::Delete);
        Ok(self.c.query(raw, args).await?)
    }

    async fn exec(&self, raw: &str, args: Args) -> Result<ExecResult> {
        Ok(self.c.exec(raw.into(), args).await?)
    }
}