tank-duckdb 0.5.0

DuckDB driver implementation for Tank: the Rust data layer
Documentation
use crate::{DuckDBConnection, DuckDBDriver};
use tank_core::{
    Driver, Executor, Query, QueryResult, Result, RowLabeled, SqlWriter, Transaction,
    future::TryFutureExt, stream::Stream,
};

pub struct DuckDBTransaction<'c> {
    connection: &'c mut DuckDBConnection,
}

impl<'c> DuckDBTransaction<'c> {
    pub async fn new(connection: &'c mut DuckDBConnection) -> Result<Self> {
        let result = Self { connection };
        let mut sql = String::new();
        result
            .connection
            .driver()
            .sql_writer()
            .write_transaction_begin(&mut sql);
        result.connection.execute(sql.into()).await?;
        Ok(result)
    }
}

impl<'c> Executor for DuckDBTransaction<'c> {
    type Driver = DuckDBDriver;

    fn driver(&self) -> &DuckDBDriver {
        self.connection.driver()
    }

    fn prepare(
        &mut self,
        query: String,
    ) -> impl Future<Output = Result<Query<DuckDBDriver>>> + Send {
        self.connection.prepare(query)
    }

    fn run(
        &mut self,
        query: tank_core::Query<Self::Driver>,
    ) -> impl Stream<Item = Result<QueryResult>> + Send {
        self.connection.run(query)
    }

    fn fetch<'s>(
        &'s mut self,
        query: Query<DuckDBDriver>,
    ) -> impl Stream<Item = Result<RowLabeled>> + Send + 's {
        self.connection.fetch(query)
    }

    fn execute(
        &mut self,
        query: tank_core::Query<Self::Driver>,
    ) -> impl Future<Output = tank_core::Result<tank_core::RowsAffected>> + Send {
        self.connection.execute(query)
    }

    fn append<'a, E, It>(
        &mut self,
        entities: It,
    ) -> impl Future<Output = tank_core::Result<tank_core::RowsAffected>> + Send
    where
        E: tank_core::Entity + 'a,
        It: IntoIterator<Item = &'a E> + Send,
    {
        self.connection.append(entities)
    }
}

impl<'c> Transaction<'c> for DuckDBTransaction<'c> {
    fn commit(self) -> impl Future<Output = Result<()>> {
        let mut sql = String::new();
        self.driver()
            .sql_writer()
            .write_transaction_commit(&mut sql);
        self.connection.execute(sql.into()).map_ok(|_| ())
    }

    fn rollback(self) -> impl Future<Output = Result<()>> {
        let mut sql = String::new();
        self.driver()
            .sql_writer()
            .write_transaction_rollback(&mut sql);
        self.connection.execute(sql.into()).map_ok(|_| ())
    }
}